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