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