github.com/zhongdalu/gf@v1.0.0/g/container/gset/gset.go (about) 1 // Copyright 2017 gf Author(https://github.com/zhongdalu/gf). 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/zhongdalu/gf. 6 7 // Package gset provides kinds of concurrent-safe/unsafe sets. 8 package gset 9 10 import ( 11 "github.com/zhongdalu/gf/g/internal/rwmutex" 12 "github.com/zhongdalu/gf/g/util/gconv" 13 "strings" 14 ) 15 16 type Set struct { 17 mu *rwmutex.RWMutex 18 m map[interface{}]struct{} 19 } 20 21 // New create and returns a new set, which contains un-repeated items. 22 // The parameter <unsafe> used to specify whether using set in un-concurrent-safety, 23 // which is false in default. 24 func New(unsafe ...bool) *Set { 25 return NewSet(unsafe...) 26 } 27 28 // See New. 29 func NewSet(unsafe ...bool) *Set { 30 return &Set{ 31 m: make(map[interface{}]struct{}), 32 mu: rwmutex.New(unsafe...), 33 } 34 } 35 36 // NewFrom returns a new set from <items>. 37 // Parameter <items> can be either a variable of any type, or a slice. 38 func NewFrom(items interface{}, unsafe ...bool) *Set { 39 m := make(map[interface{}]struct{}) 40 for _, v := range gconv.Interfaces(items) { 41 m[v] = struct{}{} 42 } 43 return &Set{ 44 m: m, 45 mu: rwmutex.New(unsafe...), 46 } 47 } 48 49 // Iterator iterates the set with given callback function <f>, 50 // if <f> returns true then continue iterating; or false to stop. 51 func (set *Set) Iterator(f func(v interface{}) bool) *Set { 52 set.mu.RLock() 53 defer set.mu.RUnlock() 54 for k, _ := range set.m { 55 if !f(k) { 56 break 57 } 58 } 59 return set 60 } 61 62 // Add adds one or multiple items to the set. 63 func (set *Set) Add(item ...interface{}) *Set { 64 set.mu.Lock() 65 for _, v := range item { 66 set.m[v] = struct{}{} 67 } 68 set.mu.Unlock() 69 return set 70 } 71 72 // Contains checks whether the set contains <item>. 73 func (set *Set) Contains(item interface{}) bool { 74 set.mu.RLock() 75 _, exists := set.m[item] 76 set.mu.RUnlock() 77 return exists 78 } 79 80 // Remove deletes <item> from set. 81 func (set *Set) Remove(item interface{}) *Set { 82 set.mu.Lock() 83 delete(set.m, item) 84 set.mu.Unlock() 85 return set 86 } 87 88 // Size returns the size of the set. 89 func (set *Set) Size() int { 90 set.mu.RLock() 91 l := len(set.m) 92 set.mu.RUnlock() 93 return l 94 } 95 96 // Clear deletes all items of the set. 97 func (set *Set) Clear() *Set { 98 set.mu.Lock() 99 set.m = make(map[interface{}]struct{}) 100 set.mu.Unlock() 101 return set 102 } 103 104 // Slice returns the a of items of the set as slice. 105 func (set *Set) Slice() []interface{} { 106 set.mu.RLock() 107 i := 0 108 ret := make([]interface{}, len(set.m)) 109 for item := range set.m { 110 ret[i] = item 111 i++ 112 } 113 set.mu.RUnlock() 114 return ret 115 } 116 117 // Join joins items with a string <glue>. 118 func (set *Set) Join(glue string) string { 119 return strings.Join(gconv.Strings(set.Slice()), ",") 120 } 121 122 // String returns items as a string, which are joined by char ','. 123 func (set *Set) String() string { 124 return set.Join(",") 125 } 126 127 // LockFunc locks writing with callback function <f>. 128 func (set *Set) LockFunc(f func(m map[interface{}]struct{})) { 129 set.mu.Lock() 130 defer set.mu.Unlock() 131 f(set.m) 132 } 133 134 // RLockFunc locks reading with callback function <f>. 135 func (set *Set) RLockFunc(f func(m map[interface{}]struct{})) { 136 set.mu.RLock() 137 defer set.mu.RUnlock() 138 f(set.m) 139 } 140 141 // Equal checks whether the two sets equal. 142 func (set *Set) Equal(other *Set) bool { 143 if set == other { 144 return true 145 } 146 set.mu.RLock() 147 defer set.mu.RUnlock() 148 other.mu.RLock() 149 defer other.mu.RUnlock() 150 if len(set.m) != len(other.m) { 151 return false 152 } 153 for key := range set.m { 154 if _, ok := other.m[key]; !ok { 155 return false 156 } 157 } 158 return true 159 } 160 161 // IsSubsetOf checks whether the current set is a sub-set of <other>. 162 func (set *Set) IsSubsetOf(other *Set) bool { 163 if set == other { 164 return true 165 } 166 set.mu.RLock() 167 defer set.mu.RUnlock() 168 other.mu.RLock() 169 defer other.mu.RUnlock() 170 for key := range set.m { 171 if _, ok := other.m[key]; !ok { 172 return false 173 } 174 } 175 return true 176 } 177 178 // Union returns a new set which is the union of <set> and <others>. 179 // Which means, all the items in <newSet> are in <set> or in <others>. 180 func (set *Set) Union(others ...*Set) (newSet *Set) { 181 newSet = NewSet(true) 182 set.mu.RLock() 183 defer set.mu.RUnlock() 184 for _, other := range others { 185 if set != other { 186 other.mu.RLock() 187 } 188 for k, v := range set.m { 189 newSet.m[k] = v 190 } 191 if set != other { 192 for k, v := range other.m { 193 newSet.m[k] = v 194 } 195 } 196 if set != other { 197 other.mu.RUnlock() 198 } 199 } 200 201 return 202 } 203 204 // Diff returns a new set which is the difference set from <set> to <others>. 205 // Which means, all the items in <newSet> are in <set> but not in <others>. 206 func (set *Set) Diff(others ...*Set) (newSet *Set) { 207 newSet = NewSet(true) 208 set.mu.RLock() 209 defer set.mu.RUnlock() 210 for _, other := range others { 211 if set == other { 212 continue 213 } 214 other.mu.RLock() 215 for k, v := range set.m { 216 if _, ok := other.m[k]; !ok { 217 newSet.m[k] = v 218 } 219 } 220 other.mu.RUnlock() 221 } 222 return 223 } 224 225 // Intersect returns a new set which is the intersection from <set> to <others>. 226 // Which means, all the items in <newSet> are in <set> and also in <others>. 227 func (set *Set) Intersect(others ...*Set) (newSet *Set) { 228 newSet = NewSet(true) 229 set.mu.RLock() 230 defer set.mu.RUnlock() 231 for _, other := range others { 232 if set != other { 233 other.mu.RLock() 234 } 235 for k, v := range set.m { 236 if _, ok := other.m[k]; ok { 237 newSet.m[k] = v 238 } 239 } 240 if set != other { 241 other.mu.RUnlock() 242 } 243 } 244 return 245 } 246 247 // Complement returns a new set which is the complement from <set> to <full>. 248 // Which means, all the items in <newSet> are in <full> and not in <set>. 249 // 250 // It returns the difference between <full> and <set> 251 // if the given set <full> is not the full set of <set>. 252 func (set *Set) Complement(full *Set) (newSet *Set) { 253 newSet = NewSet(true) 254 set.mu.RLock() 255 defer set.mu.RUnlock() 256 if set != full { 257 full.mu.RLock() 258 defer full.mu.RUnlock() 259 } 260 for k, v := range full.m { 261 if _, ok := set.m[k]; !ok { 262 newSet.m[k] = v 263 } 264 } 265 return 266 } 267 268 // Merge adds items from <others> sets into <set>. 269 func (set *Set) Merge(others ...*Set) *Set { 270 set.mu.Lock() 271 defer set.mu.Unlock() 272 for _, other := range others { 273 if set != other { 274 other.mu.RLock() 275 } 276 for k, v := range other.m { 277 set.m[k] = v 278 } 279 if set != other { 280 other.mu.RUnlock() 281 } 282 } 283 return set 284 } 285 286 // Sum sums items. 287 // Note: The items should be converted to int type, 288 // or you'd get a result that you unexpected. 289 func (set *Set) Sum() (sum int) { 290 set.mu.RLock() 291 defer set.mu.RUnlock() 292 for k, _ := range set.m { 293 sum += gconv.Int(k) 294 } 295 return 296 } 297 298 // Pops randomly pops an item from set. 299 func (set *Set) Pop(size int) interface{} { 300 set.mu.RLock() 301 defer set.mu.RUnlock() 302 for k, _ := range set.m { 303 return k 304 } 305 return nil 306 } 307 308 // Pops randomly pops <size> items from set. 309 func (set *Set) Pops(size int) []interface{} { 310 set.mu.RLock() 311 defer set.mu.RUnlock() 312 if size > len(set.m) { 313 size = len(set.m) 314 } 315 index := 0 316 array := make([]interface{}, size) 317 for k, _ := range set.m { 318 array[index] = k 319 index++ 320 if index == size { 321 break 322 } 323 } 324 return array 325 }