7 // Set defines a thread safe set data structure.
10 l sync.RWMutex // we name it because we don't want to expose it
13 // New creates and initialize a new Set. It's accept a variable number of
14 // arguments to populate the initial set. If nothing passed a Set with zero
16 func New(items ...interface{}) *Set {
18 s.m = make(map[interface{}]struct{})
20 // Ensure interface compliance
27 // New creates and initalizes a new Set interface. It accepts a variable
28 // number of arguments to populate the initial set. If nothing is passed a
29 // zero size Set based on the struct is created.
30 func (s *Set) New(items ...interface{}) Interface {
34 // Add includes the specified items (one or more) to the set. The underlying
35 // Set s is modified. If passed nothing it silently returns.
36 func (s *Set) Add(items ...interface{}) {
44 for _, item := range items {
49 // Remove deletes the specified items from the set. The underlying Set s is
50 // modified. If passed nothing it silently returns.
51 func (s *Set) Remove(items ...interface{}) {
59 for _, item := range items {
64 // Pop deletes and return an item from the set. The underlying Set s is
65 // modified. If set is empty, nil is returned.
66 func (s *Set) Pop() interface{} {
68 for item := range s.m {
79 // Has looks for the existence of items passed. It returns false if nothing is
80 // passed. For multiple items it returns true only if all of the items exist.
81 func (s *Set) Has(items ...interface{}) bool {
82 // assume checked for empty item, which not exist
91 for _, item := range items {
92 if _, has = s.m[item]; !has {
99 // Size returns the number of items in a set.
100 func (s *Set) Size() int {
108 // Clear removes all items from the set.
109 func (s *Set) Clear() {
113 s.m = make(map[interface{}]struct{})
116 // IsEqual test whether s and t are the same in size and have the same items.
117 func (s *Set) IsEqual(t Interface) bool {
121 // Force locking only if given set is threadsafe.
122 if conv, ok := t.(*Set); ok {
124 defer conv.l.RUnlock()
127 // return false if they are no the same size
128 if sameSize := len(s.m) == t.Size(); !sameSize {
133 t.Each(func(item interface{}) bool {
135 return equal // if false, Each() will end
141 // IsSubset tests whether t is a subset of s.
142 func (s *Set) IsSubset(t Interface) (subset bool) {
148 t.Each(func(item interface{}) bool {
149 _, subset = s.m[item]
156 // Each traverses the items in the Set, calling the provided function for each
157 // set member. Traversal will continue until all items in the Set have been
158 // visited, or if the closure returns false.
159 func (s *Set) Each(f func(item interface{}) bool) {
163 for item := range s.m {
170 // List returns a slice of all items. There is also StringSlice() and
171 // IntSlice() methods for returning slices of type string or int.
172 func (s *Set) List() []interface{} {
176 list := make([]interface{}, 0, len(s.m))
178 for item := range s.m {
179 list = append(list, item)
185 // Copy returns a new Set with a copy of s.
186 func (s *Set) Copy() Interface {
187 return New(s.List()...)
190 // Merge is like Union, however it modifies the current set it's applied on
191 // with the given t set.
192 func (s *Set) Merge(t Interface) {
196 t.Each(func(item interface{}) bool {
197 s.m[item] = keyExists