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