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