github.com/jxskiss/gopkg@v0.17.3/set/set.go (about) 1 package set 2 3 import ( 4 "fmt" 5 "reflect" 6 ) 7 8 const minSize = 8 9 10 // Set is set collection of general type. 11 // The zero value of Set is an empty instance ready to use. A zero Set 12 // value shall not be copied, or it may result incorrect behavior. 13 type Set struct { 14 m map[interface{}]struct{} 15 } 16 17 // NewSet creates a Set instance and add the given values into the set. 18 // If given only one param which is a slice, the elements of the slice 19 // will be added into the set using reflection. 20 func NewSet(vals ...interface{}) Set { 21 size := max(len(vals), minSize) 22 set := Set{ 23 m: make(map[interface{}]struct{}, size), 24 } 25 if len(vals) == 1 && reflect.TypeOf(vals[0]).Kind() == reflect.Slice { 26 values := reflect.ValueOf(vals[0]) 27 for i := 0; i < values.Len(); i++ { 28 set.m[values.Index(i).Interface()] = struct{}{} 29 } 30 } else { 31 set.Add(vals...) 32 } 33 return set 34 } 35 36 // NewSetWithSize creates Set instance with given initial size. 37 func NewSetWithSize(size int) Set { 38 set := Set{ 39 m: make(map[interface{}]struct{}, size), 40 } 41 return set 42 } 43 44 // Size returns the size of the set. 45 func (s Set) Size() int { return len(s.m) } 46 47 // Add adds the given values into the set. 48 // If given only one param and which is a slice, the elements of the slice 49 // will be added into the set using reflection. 50 func (s *Set) Add(vals ...interface{}) { 51 if s.m == nil { 52 size := max(len(vals), minSize) 53 s.m = make(map[interface{}]struct{}, size) 54 } 55 if len(vals) == 1 && reflect.TypeOf(vals[0]).Kind() == reflect.Slice { 56 values := reflect.ValueOf(vals[0]) 57 for i := 0; i < values.Len(); i++ { 58 s.m[values.Index(i).Interface()] = struct{}{} 59 } 60 return 61 } 62 63 for idx := range vals { 64 s.m[vals[idx]] = struct{}{} 65 } 66 } 67 68 // Del deletes values from the set. 69 func (s *Set) Del(vals ...interface{}) { 70 if len(vals) == 1 && reflect.TypeOf(vals[0]).Kind() == reflect.Slice { 71 values := reflect.ValueOf(vals[0]) 72 for i := 0; i < values.Len(); i++ { 73 delete(s.m, values.Index(i).Interface()) 74 } 75 return 76 } 77 78 for idx := range vals { 79 delete(s.m, vals[idx]) 80 } 81 } 82 83 // Pop pops an element from the set, in no particular order. 84 func (s *Set) Pop() interface{} { 85 for val := range s.m { 86 delete(s.m, val) 87 return val 88 } 89 return nil 90 } 91 92 // Iterate iterates the set in no particular order and call the given 93 // function for each set element. 94 func (s Set) Iterate(fn func(interface{})) { 95 for val := range s.m { 96 fn(val) 97 } 98 } 99 100 // Contains returns true if the set contains all the values. 101 func (s Set) Contains(vals ...interface{}) bool { 102 if len(vals) == 0 { 103 return false 104 } 105 for _, v := range vals { 106 if _, ok := s.m[v]; !ok { 107 return false 108 } 109 } 110 return true 111 } 112 113 // ContainsAny returns true if the set contains any of the values. 114 func (s Set) ContainsAny(vals ...interface{}) bool { 115 for _, v := range vals { 116 if _, ok := s.m[v]; ok { 117 return true 118 } 119 } 120 return false 121 } 122 123 // Diff returns new Set about the values which other sets don't contain. 124 func (s Set) Diff(other Set) Set { 125 res := NewSetWithSize(s.Size()) 126 127 for val := range s.m { 128 if _, ok := other.m[val]; !ok { 129 res.m[val] = struct{}{} 130 } 131 } 132 return res 133 } 134 135 // DiffSlice is similar to Diff, but takes a slice as parameter. 136 // Param other must be a slice of []interface{} or slice of the concrete 137 // element type, else it panics. 138 func (s Set) DiffSlice(other interface{}) Set { 139 otherTyp := reflect.TypeOf(other) 140 if otherTyp == nil || otherTyp.Kind() != reflect.Slice { 141 panic(fmt.Sprintf("invalid other type %T", other)) 142 } 143 144 otherVal := reflect.ValueOf(other) 145 otherLen := otherVal.Len() 146 if len(s.m) > otherLen { 147 tmp := NewSetWithSize(otherLen) 148 dup := 0 149 for i := 0; i < otherLen; i++ { 150 val := otherVal.Index(i).Interface() 151 if _, ok := s.m[val]; ok { 152 dup++ 153 } 154 tmp.m[val] = struct{}{} 155 } 156 res := NewSetWithSize(max(s.Size()-dup, 0)) 157 for val := range s.m { 158 if _, ok := tmp.m[val]; !ok { 159 res.m[val] = struct{}{} 160 } 161 } 162 return res 163 } else { 164 res := NewSetWithSize(s.Size()) 165 for val := range s.m { 166 res.m[val] = struct{}{} 167 } 168 for i := 0; i < otherLen; i++ { 169 val := otherVal.Index(i).Interface() 170 if _, ok := res.m[val]; ok { 171 delete(res.m, val) 172 } 173 } 174 return res 175 } 176 } 177 178 // FilterInclude returns a new slice which contains values that present in 179 // the provided slice and also present in the Set. 180 // Param slice must be a slice of []interface{} or slice of the concrete 181 // element type, else it panics. 182 func (s Set) FilterInclude(slice interface{}) interface{} { 183 sliceTyp := reflect.TypeOf(slice) 184 if sliceTyp == nil || sliceTyp.Kind() != reflect.Slice { 185 panic(fmt.Sprintf("invalid slice type %T", slice)) 186 } 187 188 sliceVal := reflect.ValueOf(slice) 189 sliceLen := sliceVal.Len() 190 res := reflect.MakeSlice(sliceTyp, 0, min(s.Size(), sliceLen)) 191 for i := 0; i < sliceLen; i++ { 192 val := sliceVal.Index(i) 193 if _, ok := s.m[val.Interface()]; ok { 194 res = reflect.Append(res, val) 195 } 196 } 197 return res.Interface() 198 } 199 200 // FilterExclude returns a new slice which contains values that present in 201 // the provided slice but don't present in the Set. 202 // Param slice must be a slice of []interface{} or slice of the concrete 203 // element type, else it panics. 204 func (s Set) FilterExclude(slice interface{}) interface{} { 205 sliceTyp := reflect.TypeOf(slice) 206 if sliceTyp == nil || sliceTyp.Kind() != reflect.Slice { 207 panic(fmt.Sprintf("invalid slice type %T", slice)) 208 } 209 210 sliceVal := reflect.ValueOf(slice) 211 sliceLen := sliceVal.Len() 212 res := reflect.MakeSlice(sliceTyp, 0, sliceLen) 213 for i := 0; i < sliceLen; i++ { 214 val := sliceVal.Index(i) 215 if _, ok := s.m[val.Interface()]; !ok { 216 res = reflect.Append(res, val) 217 } 218 } 219 return res.Interface() 220 } 221 222 // Intersect returns new Set about values which other set also contains. 223 func (s Set) Intersect(other Set) Set { 224 res := NewSetWithSize(min(s.Size(), other.Size())) 225 226 // loop over the smaller set 227 if len(s.m) <= len(other.m) { 228 for val := range s.m { 229 if _, ok := other.m[val]; ok { 230 res.m[val] = struct{}{} 231 } 232 } 233 } else { 234 for val := range other.m { 235 if _, ok := s.m[val]; ok { 236 res.m[val] = struct{}{} 237 } 238 } 239 } 240 return res 241 } 242 243 // IntersectSlice is similar to Intersect, but takes a slice as parameter. 244 // Param other must be a slice of []interface{} or slice of the concrete 245 // element type, else it panics. 246 func (s Set) IntersectSlice(other interface{}) Set { 247 otherTyp := reflect.TypeOf(other) 248 if otherTyp == nil || otherTyp.Kind() != reflect.Slice { 249 panic(fmt.Sprintf("invalid other type %T", other)) 250 } 251 252 otherVal := reflect.ValueOf(other) 253 otherLen := otherVal.Len() 254 res := NewSetWithSize(min(s.Size(), otherLen)) 255 for i := 0; i < otherLen; i++ { 256 val := otherVal.Index(i).Interface() 257 if _, ok := s.m[val]; ok { 258 res.m[val] = struct{}{} 259 } 260 } 261 return res 262 } 263 264 // Union returns new Set about values either in the set or the other set. 265 func (s Set) Union(other Set) Set { 266 res := NewSetWithSize(s.Size() + other.Size()) 267 268 for val := range s.m { 269 res.m[val] = struct{}{} 270 } 271 for val := range other.m { 272 res.m[val] = struct{}{} 273 } 274 return res 275 } 276 277 // UnionSlice is similar to Union, but takes a slice as parameter. 278 // Param other must be a slice of []interface{} or slice of the concrete 279 // element type, else it panics. 280 func (s Set) UnionSlice(other interface{}) Set { 281 otherTyp := reflect.TypeOf(other) 282 if otherTyp == nil || otherTyp.Kind() != reflect.Slice { 283 panic(fmt.Sprintf("invalid other type %T", other)) 284 } 285 286 otherVal := reflect.ValueOf(other) 287 otherLen := otherVal.Len() 288 res := NewSetWithSize(s.Size() + otherLen) 289 for val := range s.m { 290 res.m[val] = struct{}{} 291 } 292 for i := 0; i < otherLen; i++ { 293 val := otherVal.Index(i).Interface() 294 res.m[val] = struct{}{} 295 } 296 return res 297 } 298 299 // Slice converts set into a []interface{} slice. 300 func (s Set) Slice() []interface{} { 301 res := make([]interface{}, 0, len(s.m)) 302 for val := range s.m { 303 res = append(res, val) 304 } 305 return res 306 } 307 308 // Map converts set into map[interface{}]bool. 309 func (s Set) Map() map[interface{}]bool { 310 res := make(map[interface{}]bool, len(s.m)) 311 for val := range s.m { 312 res[val] = true 313 } 314 return res 315 } 316 317 func min(a, b int) int { 318 if a < b { 319 return a 320 } 321 return b 322 } 323 324 func max(a, b int) int { 325 if a > b { 326 return a 327 } 328 return b 329 }