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  }