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