8 // Provides a common set baseline for both threadsafe and non-ts Sets.
10 m map[interface{}]struct{} // struct{} doesn't take up space
13 // SetNonTS defines a non-thread safe set data structure.
14 type SetNonTS struct {
18 // NewNonTS creates and initialize a new non-threadsafe Set.
19 // It accepts a variable number of arguments to populate the initial set.
20 // If nothing is passed a SetNonTS with zero size is created.
21 func NewNonTS(items ...interface{}) *SetNonTS {
23 s.m = make(map[interface{}]struct{})
25 // Ensure interface compliance
32 // New creates and initalizes a new Set interface. It accepts a variable
33 // number of arguments to populate the initial set. If nothing is passed a
34 // zero size Set based on the struct is created.
35 func (s *set) New(items ...interface{}) Interface {
36 return NewNonTS(items...)
39 // Add includes the specified items (one or more) to the set. The underlying
40 // Set s is modified. If passed nothing it silently returns.
41 func (s *set) Add(items ...interface{}) {
46 for _, item := range items {
51 // Remove deletes the specified items from the set. The underlying Set s is
52 // modified. If passed nothing it silently returns.
53 func (s *set) Remove(items ...interface{}) {
58 for _, item := range items {
63 // Pop deletes and return an item from the set. The underlying Set s is
64 // modified. If set is empty, nil is returned.
65 func (s *set) Pop() interface{} {
66 for item := range s.m {
73 // Has looks for the existence of items passed. It returns false if nothing is
74 // passed. For multiple items it returns true only if all of the items exist.
75 func (s *set) Has(items ...interface{}) bool {
76 // assume checked for empty item, which not exist
82 for _, item := range items {
83 if _, has = s.m[item]; !has {
90 // Size returns the number of items in a set.
91 func (s *set) Size() int {
95 // Clear removes all items from the set.
96 func (s *set) Clear() {
97 s.m = make(map[interface{}]struct{})
100 // IsEmpty reports whether the Set is empty.
101 func (s *set) IsEmpty() bool {
105 // IsEqual test whether s and t are the same in size and have the same items.
106 func (s *set) IsEqual(t Interface) bool {
107 // Force locking only if given set is threadsafe.
108 if conv, ok := t.(*Set); ok {
110 defer conv.l.RUnlock()
113 // return false if they are no the same size
114 if sameSize := len(s.m) == t.Size(); !sameSize {
119 t.Each(func(item interface{}) bool {
121 return equal // if false, Each() will end
127 // IsSubset tests whether t is a subset of s.
128 func (s *set) IsSubset(t Interface) (subset bool) {
131 t.Each(func(item interface{}) bool {
132 _, subset = s.m[item]
139 // IsSuperset tests whether t is a superset of s.
140 func (s *set) IsSuperset(t Interface) bool {
144 // Each traverses the items in the Set, calling the provided function for each
145 // set member. Traversal will continue until all items in the Set have been
146 // visited, or if the closure returns false.
147 func (s *set) Each(f func(item interface{}) bool) {
148 for item := range s.m {
155 // String returns a string representation of s
156 func (s *set) String() string {
157 t := make([]string, 0, len(s.List()))
158 for _, item := range s.List() {
159 t = append(t, fmt.Sprintf("%v", item))
162 return fmt.Sprintf("[%s]", strings.Join(t, ", "))
165 // List returns a slice of all items. There is also StringSlice() and
166 // IntSlice() methods for returning slices of type string or int.
167 func (s *set) List() []interface{} {
168 list := make([]interface{}, 0, len(s.m))
170 for item := range s.m {
171 list = append(list, item)
177 // Copy returns a new Set with a copy of s.
178 func (s *set) Copy() Interface {
179 return NewNonTS(s.List()...)
182 // Merge is like Union, however it modifies the current set it's applied on
183 // with the given t set.
184 func (s *set) Merge(t Interface) {
185 t.Each(func(item interface{}) bool {
186 s.m[item] = keyExists
191 // it's not the opposite of Merge.
192 // Separate removes the set items containing in t from set s. Please aware that
193 func (s *set) Separate(t Interface) {
194 s.Remove(t.List()...)