github.com/gogf/gf@v1.16.9/container/gset/gset_int_set.go (about) 1 // Copyright GoFrame Author(https://goframe.org). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/gogf/gf. 6 // 7 8 package gset 9 10 import ( 11 "bytes" 12 "github.com/gogf/gf/internal/json" 13 "github.com/gogf/gf/internal/rwmutex" 14 "github.com/gogf/gf/util/gconv" 15 ) 16 17 type IntSet struct { 18 mu rwmutex.RWMutex 19 data map[int]struct{} 20 } 21 22 // New create and returns a new set, which contains un-repeated items. 23 // The parameter <safe> is used to specify whether using set in concurrent-safety, 24 // which is false in default. 25 func NewIntSet(safe ...bool) *IntSet { 26 return &IntSet{ 27 mu: rwmutex.Create(safe...), 28 data: make(map[int]struct{}), 29 } 30 } 31 32 // NewIntSetFrom returns a new set from <items>. 33 func NewIntSetFrom(items []int, safe ...bool) *IntSet { 34 m := make(map[int]struct{}) 35 for _, v := range items { 36 m[v] = struct{}{} 37 } 38 return &IntSet{ 39 mu: rwmutex.Create(safe...), 40 data: m, 41 } 42 } 43 44 // Iterator iterates the set readonly with given callback function <f>, 45 // if <f> returns true then continue iterating; or false to stop. 46 func (set *IntSet) Iterator(f func(v int) bool) { 47 set.mu.RLock() 48 defer set.mu.RUnlock() 49 for k, _ := range set.data { 50 if !f(k) { 51 break 52 } 53 } 54 } 55 56 // Add adds one or multiple items to the set. 57 func (set *IntSet) Add(item ...int) { 58 set.mu.Lock() 59 if set.data == nil { 60 set.data = make(map[int]struct{}) 61 } 62 for _, v := range item { 63 set.data[v] = struct{}{} 64 } 65 set.mu.Unlock() 66 } 67 68 // AddIfNotExist checks whether item exists in the set, 69 // it adds the item to set and returns true if it does not exists in the set, 70 // or else it does nothing and returns false. 71 // 72 // Note that, if <item> is nil, it does nothing and returns false. 73 func (set *IntSet) AddIfNotExist(item int) bool { 74 if !set.Contains(item) { 75 set.mu.Lock() 76 defer set.mu.Unlock() 77 if set.data == nil { 78 set.data = make(map[int]struct{}) 79 } 80 if _, ok := set.data[item]; !ok { 81 set.data[item] = struct{}{} 82 return true 83 } 84 } 85 return false 86 } 87 88 // AddIfNotExistFunc checks whether item exists in the set, 89 // it adds the item to set and returns true if it does not exists in the set and 90 // function <f> returns true, or else it does nothing and returns false. 91 // 92 // Note that, the function <f> is executed without writing lock. 93 func (set *IntSet) AddIfNotExistFunc(item int, f func() bool) bool { 94 if !set.Contains(item) { 95 if f() { 96 set.mu.Lock() 97 defer set.mu.Unlock() 98 if set.data == nil { 99 set.data = make(map[int]struct{}) 100 } 101 if _, ok := set.data[item]; !ok { 102 set.data[item] = struct{}{} 103 return true 104 } 105 } 106 } 107 return false 108 } 109 110 // AddIfNotExistFunc checks whether item exists in the set, 111 // it adds the item to set and returns true if it does not exists in the set and 112 // function <f> returns true, or else it does nothing and returns false. 113 // 114 // Note that, the function <f> is executed without writing lock. 115 func (set *IntSet) AddIfNotExistFuncLock(item int, f func() bool) bool { 116 if !set.Contains(item) { 117 set.mu.Lock() 118 defer set.mu.Unlock() 119 if set.data == nil { 120 set.data = make(map[int]struct{}) 121 } 122 if f() { 123 if _, ok := set.data[item]; !ok { 124 set.data[item] = struct{}{} 125 return true 126 } 127 } 128 } 129 return false 130 } 131 132 // Contains checks whether the set contains <item>. 133 func (set *IntSet) Contains(item int) bool { 134 var ok bool 135 set.mu.RLock() 136 if set.data != nil { 137 _, ok = set.data[item] 138 } 139 set.mu.RUnlock() 140 return ok 141 } 142 143 // Remove deletes <item> from set. 144 func (set *IntSet) Remove(item int) { 145 set.mu.Lock() 146 if set.data != nil { 147 delete(set.data, item) 148 } 149 set.mu.Unlock() 150 } 151 152 // Size returns the size of the set. 153 func (set *IntSet) Size() int { 154 set.mu.RLock() 155 l := len(set.data) 156 set.mu.RUnlock() 157 return l 158 } 159 160 // Clear deletes all items of the set. 161 func (set *IntSet) Clear() { 162 set.mu.Lock() 163 set.data = make(map[int]struct{}) 164 set.mu.Unlock() 165 } 166 167 // Slice returns the a of items of the set as slice. 168 func (set *IntSet) Slice() []int { 169 set.mu.RLock() 170 var ( 171 i = 0 172 ret = make([]int, len(set.data)) 173 ) 174 for k, _ := range set.data { 175 ret[i] = k 176 i++ 177 } 178 set.mu.RUnlock() 179 return ret 180 } 181 182 // Join joins items with a string <glue>. 183 func (set *IntSet) Join(glue string) string { 184 set.mu.RLock() 185 defer set.mu.RUnlock() 186 if len(set.data) == 0 { 187 return "" 188 } 189 var ( 190 l = len(set.data) 191 i = 0 192 buffer = bytes.NewBuffer(nil) 193 ) 194 for k, _ := range set.data { 195 buffer.WriteString(gconv.String(k)) 196 if i != l-1 { 197 buffer.WriteString(glue) 198 } 199 i++ 200 } 201 return buffer.String() 202 } 203 204 // String returns items as a string, which implements like json.Marshal does. 205 func (set *IntSet) String() string { 206 return "[" + set.Join(",") + "]" 207 } 208 209 // LockFunc locks writing with callback function <f>. 210 func (set *IntSet) LockFunc(f func(m map[int]struct{})) { 211 set.mu.Lock() 212 defer set.mu.Unlock() 213 f(set.data) 214 } 215 216 // RLockFunc locks reading with callback function <f>. 217 func (set *IntSet) RLockFunc(f func(m map[int]struct{})) { 218 set.mu.RLock() 219 defer set.mu.RUnlock() 220 f(set.data) 221 } 222 223 // Equal checks whether the two sets equal. 224 func (set *IntSet) Equal(other *IntSet) bool { 225 if set == other { 226 return true 227 } 228 set.mu.RLock() 229 defer set.mu.RUnlock() 230 other.mu.RLock() 231 defer other.mu.RUnlock() 232 if len(set.data) != len(other.data) { 233 return false 234 } 235 for key := range set.data { 236 if _, ok := other.data[key]; !ok { 237 return false 238 } 239 } 240 return true 241 } 242 243 // IsSubsetOf checks whether the current set is a sub-set of <other>. 244 func (set *IntSet) IsSubsetOf(other *IntSet) bool { 245 if set == other { 246 return true 247 } 248 set.mu.RLock() 249 defer set.mu.RUnlock() 250 other.mu.RLock() 251 defer other.mu.RUnlock() 252 for key := range set.data { 253 if _, ok := other.data[key]; !ok { 254 return false 255 } 256 } 257 return true 258 } 259 260 // Union returns a new set which is the union of <set> and <other>. 261 // Which means, all the items in <newSet> are in <set> or in <other>. 262 func (set *IntSet) Union(others ...*IntSet) (newSet *IntSet) { 263 newSet = NewIntSet() 264 set.mu.RLock() 265 defer set.mu.RUnlock() 266 for _, other := range others { 267 if set != other { 268 other.mu.RLock() 269 } 270 for k, v := range set.data { 271 newSet.data[k] = v 272 } 273 if set != other { 274 for k, v := range other.data { 275 newSet.data[k] = v 276 } 277 } 278 if set != other { 279 other.mu.RUnlock() 280 } 281 } 282 283 return 284 } 285 286 // Diff returns a new set which is the difference set from <set> to <other>. 287 // Which means, all the items in <newSet> are in <set> but not in <other>. 288 func (set *IntSet) Diff(others ...*IntSet) (newSet *IntSet) { 289 newSet = NewIntSet() 290 set.mu.RLock() 291 defer set.mu.RUnlock() 292 for _, other := range others { 293 if set == other { 294 continue 295 } 296 other.mu.RLock() 297 for k, v := range set.data { 298 if _, ok := other.data[k]; !ok { 299 newSet.data[k] = v 300 } 301 } 302 other.mu.RUnlock() 303 } 304 return 305 } 306 307 // Intersect returns a new set which is the intersection from <set> to <other>. 308 // Which means, all the items in <newSet> are in <set> and also in <other>. 309 func (set *IntSet) Intersect(others ...*IntSet) (newSet *IntSet) { 310 newSet = NewIntSet() 311 set.mu.RLock() 312 defer set.mu.RUnlock() 313 for _, other := range others { 314 if set != other { 315 other.mu.RLock() 316 } 317 for k, v := range set.data { 318 if _, ok := other.data[k]; ok { 319 newSet.data[k] = v 320 } 321 } 322 if set != other { 323 other.mu.RUnlock() 324 } 325 } 326 return 327 } 328 329 // Complement returns a new set which is the complement from <set> to <full>. 330 // Which means, all the items in <newSet> are in <full> and not in <set>. 331 // 332 // It returns the difference between <full> and <set> 333 // if the given set <full> is not the full set of <set>. 334 func (set *IntSet) Complement(full *IntSet) (newSet *IntSet) { 335 newSet = NewIntSet() 336 set.mu.RLock() 337 defer set.mu.RUnlock() 338 if set != full { 339 full.mu.RLock() 340 defer full.mu.RUnlock() 341 } 342 for k, v := range full.data { 343 if _, ok := set.data[k]; !ok { 344 newSet.data[k] = v 345 } 346 } 347 return 348 } 349 350 // Merge adds items from <others> sets into <set>. 351 func (set *IntSet) Merge(others ...*IntSet) *IntSet { 352 set.mu.Lock() 353 defer set.mu.Unlock() 354 for _, other := range others { 355 if set != other { 356 other.mu.RLock() 357 } 358 for k, v := range other.data { 359 set.data[k] = v 360 } 361 if set != other { 362 other.mu.RUnlock() 363 } 364 } 365 return set 366 } 367 368 // Sum sums items. 369 // Note: The items should be converted to int type, 370 // or you'd get a result that you unexpected. 371 func (set *IntSet) Sum() (sum int) { 372 set.mu.RLock() 373 defer set.mu.RUnlock() 374 for k, _ := range set.data { 375 sum += k 376 } 377 return 378 } 379 380 // Pops randomly pops an item from set. 381 func (set *IntSet) Pop() int { 382 set.mu.Lock() 383 defer set.mu.Unlock() 384 for k, _ := range set.data { 385 delete(set.data, k) 386 return k 387 } 388 return 0 389 } 390 391 // Pops randomly pops <size> items from set. 392 // It returns all items if size == -1. 393 func (set *IntSet) Pops(size int) []int { 394 set.mu.Lock() 395 defer set.mu.Unlock() 396 if size > len(set.data) || size == -1 { 397 size = len(set.data) 398 } 399 if size <= 0 { 400 return nil 401 } 402 index := 0 403 array := make([]int, size) 404 for k, _ := range set.data { 405 delete(set.data, k) 406 array[index] = k 407 index++ 408 if index == size { 409 break 410 } 411 } 412 return array 413 } 414 415 // Walk applies a user supplied function <f> to every item of set. 416 func (set *IntSet) Walk(f func(item int) int) *IntSet { 417 set.mu.Lock() 418 defer set.mu.Unlock() 419 m := make(map[int]struct{}, len(set.data)) 420 for k, v := range set.data { 421 m[f(k)] = v 422 } 423 set.data = m 424 return set 425 } 426 427 // MarshalJSON implements the interface MarshalJSON for json.Marshal. 428 func (set *IntSet) MarshalJSON() ([]byte, error) { 429 return json.Marshal(set.Slice()) 430 } 431 432 // UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal. 433 func (set *IntSet) UnmarshalJSON(b []byte) error { 434 set.mu.Lock() 435 defer set.mu.Unlock() 436 if set.data == nil { 437 set.data = make(map[int]struct{}) 438 } 439 var array []int 440 if err := json.UnmarshalUseNumber(b, &array); err != nil { 441 return err 442 } 443 for _, v := range array { 444 set.data[v] = struct{}{} 445 } 446 return nil 447 } 448 449 // UnmarshalValue is an interface implement which sets any type of value for set. 450 func (set *IntSet) UnmarshalValue(value interface{}) (err error) { 451 set.mu.Lock() 452 defer set.mu.Unlock() 453 if set.data == nil { 454 set.data = make(map[int]struct{}) 455 } 456 var array []int 457 switch value.(type) { 458 case string, []byte: 459 err = json.UnmarshalUseNumber(gconv.Bytes(value), &array) 460 default: 461 array = gconv.SliceInt(value) 462 } 463 for _, v := range array { 464 set.data[v] = struct{}{} 465 } 466 return 467 }