github.com/gogf/gf/v2@v2.7.4/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 13 "github.com/gogf/gf/v2/internal/json" 14 "github.com/gogf/gf/v2/internal/rwmutex" 15 "github.com/gogf/gf/v2/util/gconv" 16 ) 17 18 // IntSet is consisted of int items. 19 type IntSet struct { 20 mu rwmutex.RWMutex 21 data map[int]struct{} 22 } 23 24 // NewIntSet create and returns a new set, which contains un-repeated items. 25 // The parameter `safe` is used to specify whether using set in concurrent-safety, 26 // which is false in default. 27 func NewIntSet(safe ...bool) *IntSet { 28 return &IntSet{ 29 mu: rwmutex.Create(safe...), 30 data: make(map[int]struct{}), 31 } 32 } 33 34 // NewIntSetFrom returns a new set from `items`. 35 func NewIntSetFrom(items []int, safe ...bool) *IntSet { 36 m := make(map[int]struct{}) 37 for _, v := range items { 38 m[v] = struct{}{} 39 } 40 return &IntSet{ 41 mu: rwmutex.Create(safe...), 42 data: m, 43 } 44 } 45 46 // Iterator iterates the set readonly with given callback function `f`, 47 // if `f` returns true then continue iterating; or false to stop. 48 func (set *IntSet) Iterator(f func(v int) bool) { 49 for _, k := range set.Slice() { 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 // AddIfNotExistFuncLock 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 an 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 if set == nil { 207 return "" 208 } 209 return "[" + set.Join(",") + "]" 210 } 211 212 // LockFunc locks writing with callback function `f`. 213 func (set *IntSet) LockFunc(f func(m map[int]struct{})) { 214 set.mu.Lock() 215 defer set.mu.Unlock() 216 f(set.data) 217 } 218 219 // RLockFunc locks reading with callback function `f`. 220 func (set *IntSet) RLockFunc(f func(m map[int]struct{})) { 221 set.mu.RLock() 222 defer set.mu.RUnlock() 223 f(set.data) 224 } 225 226 // Equal checks whether the two sets equal. 227 func (set *IntSet) Equal(other *IntSet) bool { 228 if set == other { 229 return true 230 } 231 set.mu.RLock() 232 defer set.mu.RUnlock() 233 other.mu.RLock() 234 defer other.mu.RUnlock() 235 if len(set.data) != len(other.data) { 236 return false 237 } 238 for key := range set.data { 239 if _, ok := other.data[key]; !ok { 240 return false 241 } 242 } 243 return true 244 } 245 246 // IsSubsetOf checks whether the current set is a sub-set of `other`. 247 func (set *IntSet) IsSubsetOf(other *IntSet) bool { 248 if set == other { 249 return true 250 } 251 set.mu.RLock() 252 defer set.mu.RUnlock() 253 other.mu.RLock() 254 defer other.mu.RUnlock() 255 for key := range set.data { 256 if _, ok := other.data[key]; !ok { 257 return false 258 } 259 } 260 return true 261 } 262 263 // Union returns a new set which is the union of `set` and `other`. 264 // Which means, all the items in `newSet` are in `set` or in `other`. 265 func (set *IntSet) Union(others ...*IntSet) (newSet *IntSet) { 266 newSet = NewIntSet() 267 set.mu.RLock() 268 defer set.mu.RUnlock() 269 for _, other := range others { 270 if set != other { 271 other.mu.RLock() 272 } 273 for k, v := range set.data { 274 newSet.data[k] = v 275 } 276 if set != other { 277 for k, v := range other.data { 278 newSet.data[k] = v 279 } 280 } 281 if set != other { 282 other.mu.RUnlock() 283 } 284 } 285 286 return 287 } 288 289 // Diff returns a new set which is the difference set from `set` to `other`. 290 // Which means, all the items in `newSet` are in `set` but not in `other`. 291 func (set *IntSet) Diff(others ...*IntSet) (newSet *IntSet) { 292 newSet = NewIntSet() 293 set.mu.RLock() 294 defer set.mu.RUnlock() 295 for _, other := range others { 296 if set == other { 297 continue 298 } 299 other.mu.RLock() 300 for k, v := range set.data { 301 if _, ok := other.data[k]; !ok { 302 newSet.data[k] = v 303 } 304 } 305 other.mu.RUnlock() 306 } 307 return 308 } 309 310 // Intersect returns a new set which is the intersection from `set` to `other`. 311 // Which means, all the items in `newSet` are in `set` and also in `other`. 312 func (set *IntSet) Intersect(others ...*IntSet) (newSet *IntSet) { 313 newSet = NewIntSet() 314 set.mu.RLock() 315 defer set.mu.RUnlock() 316 for _, other := range others { 317 if set != other { 318 other.mu.RLock() 319 } 320 for k, v := range set.data { 321 if _, ok := other.data[k]; ok { 322 newSet.data[k] = v 323 } 324 } 325 if set != other { 326 other.mu.RUnlock() 327 } 328 } 329 return 330 } 331 332 // Complement returns a new set which is the complement from `set` to `full`. 333 // Which means, all the items in `newSet` are in `full` and not in `set`. 334 // 335 // It returns the difference between `full` and `set` 336 // if the given set `full` is not the full set of `set`. 337 func (set *IntSet) Complement(full *IntSet) (newSet *IntSet) { 338 newSet = NewIntSet() 339 set.mu.RLock() 340 defer set.mu.RUnlock() 341 if set != full { 342 full.mu.RLock() 343 defer full.mu.RUnlock() 344 } 345 for k, v := range full.data { 346 if _, ok := set.data[k]; !ok { 347 newSet.data[k] = v 348 } 349 } 350 return 351 } 352 353 // Merge adds items from `others` sets into `set`. 354 func (set *IntSet) Merge(others ...*IntSet) *IntSet { 355 set.mu.Lock() 356 defer set.mu.Unlock() 357 for _, other := range others { 358 if set != other { 359 other.mu.RLock() 360 } 361 for k, v := range other.data { 362 set.data[k] = v 363 } 364 if set != other { 365 other.mu.RUnlock() 366 } 367 } 368 return set 369 } 370 371 // Sum sums items. 372 // Note: The items should be converted to int type, 373 // or you'd get a result that you unexpected. 374 func (set *IntSet) Sum() (sum int) { 375 set.mu.RLock() 376 defer set.mu.RUnlock() 377 for k := range set.data { 378 sum += k 379 } 380 return 381 } 382 383 // Pop randomly pops an item from set. 384 func (set *IntSet) Pop() int { 385 set.mu.Lock() 386 defer set.mu.Unlock() 387 for k := range set.data { 388 delete(set.data, k) 389 return k 390 } 391 return 0 392 } 393 394 // Pops randomly pops `size` items from set. 395 // It returns all items if size == -1. 396 func (set *IntSet) Pops(size int) []int { 397 set.mu.Lock() 398 defer set.mu.Unlock() 399 if size > len(set.data) || size == -1 { 400 size = len(set.data) 401 } 402 if size <= 0 { 403 return nil 404 } 405 index := 0 406 array := make([]int, size) 407 for k := range set.data { 408 delete(set.data, k) 409 array[index] = k 410 index++ 411 if index == size { 412 break 413 } 414 } 415 return array 416 } 417 418 // Walk applies a user supplied function `f` to every item of set. 419 func (set *IntSet) Walk(f func(item int) int) *IntSet { 420 set.mu.Lock() 421 defer set.mu.Unlock() 422 m := make(map[int]struct{}, len(set.data)) 423 for k, v := range set.data { 424 m[f(k)] = v 425 } 426 set.data = m 427 return set 428 } 429 430 // MarshalJSON implements the interface MarshalJSON for json.Marshal. 431 func (set IntSet) MarshalJSON() ([]byte, error) { 432 return json.Marshal(set.Slice()) 433 } 434 435 // UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal. 436 func (set *IntSet) UnmarshalJSON(b []byte) error { 437 set.mu.Lock() 438 defer set.mu.Unlock() 439 if set.data == nil { 440 set.data = make(map[int]struct{}) 441 } 442 var array []int 443 if err := json.UnmarshalUseNumber(b, &array); err != nil { 444 return err 445 } 446 for _, v := range array { 447 set.data[v] = struct{}{} 448 } 449 return nil 450 } 451 452 // UnmarshalValue is an interface implement which sets any type of value for set. 453 func (set *IntSet) UnmarshalValue(value interface{}) (err error) { 454 set.mu.Lock() 455 defer set.mu.Unlock() 456 if set.data == nil { 457 set.data = make(map[int]struct{}) 458 } 459 var array []int 460 switch value.(type) { 461 case string, []byte: 462 err = json.UnmarshalUseNumber(gconv.Bytes(value), &array) 463 default: 464 array = gconv.SliceInt(value) 465 } 466 for _, v := range array { 467 set.data[v] = struct{}{} 468 } 469 return 470 } 471 472 // DeepCopy implements interface for deep copy of current type. 473 func (set *IntSet) DeepCopy() interface{} { 474 if set == nil { 475 return nil 476 } 477 set.mu.RLock() 478 defer set.mu.RUnlock() 479 var ( 480 slice = make([]int, len(set.data)) 481 index = 0 482 ) 483 for k := range set.data { 484 slice[index] = k 485 index++ 486 } 487 return NewIntSetFrom(slice, set.mu.IsSafe()) 488 }