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