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  }