github.com/songzhibin97/go-baseutils@v0.0.2-0.20240302024150-487d8ce9c082/structure/sets/hashset/hashset.go (about) 1 // Package hashset implements a set backed by a hash table. 2 // 3 // Structure is not thread safe. 4 // 5 // References: http://en.wikipedia.org/wiki/Set_%28abstract_data_type%29 6 package hashset 7 8 import ( 9 "encoding/json" 10 "fmt" 11 "strings" 12 13 "github.com/songzhibin97/go-baseutils/structure/sets" 14 ) 15 16 // Assert Set implementation 17 var _ sets.Set[int] = (*Set[int])(nil) 18 19 // Set holds elements in go's native map 20 type Set[E comparable] struct { 21 items map[E]struct{} 22 } 23 24 var itemExists = struct{}{} 25 26 // New instantiates a new empty set and adds the passed values, if any, to the set 27 func New[E comparable](values ...E) *Set[E] { 28 set := &Set[E]{items: make(map[E]struct{})} 29 if len(values) > 0 { 30 set.Add(values...) 31 } 32 return set 33 } 34 35 // Add adds the items (one or more) to the set. 36 func (set *Set[E]) Add(items ...E) { 37 for _, item := range items { 38 set.items[item] = itemExists 39 } 40 } 41 42 // Remove removes the items (one or more) from the set. 43 func (set *Set[E]) Remove(items ...E) { 44 for _, item := range items { 45 delete(set.items, item) 46 } 47 } 48 49 // Contains check if items (one or more) are present in the set. 50 // All items have to be present in the set for the method to return true. 51 // Returns true if no arguments are passed at all, i.e. set is always superset of empty set. 52 func (set *Set[E]) Contains(items ...E) bool { 53 for _, item := range items { 54 if _, contains := set.items[item]; !contains { 55 return false 56 } 57 } 58 return true 59 } 60 61 // Empty returns true if set does not contain any elements. 62 func (set *Set[E]) Empty() bool { 63 return set.Size() == 0 64 } 65 66 // Size returns number of elements within the set. 67 func (set *Set[E]) Size() int { 68 return len(set.items) 69 } 70 71 // Clear clears all values in the set. 72 func (set *Set[E]) Clear() { 73 set.items = make(map[E]struct{}) 74 } 75 76 // Values returns all items in the set. 77 func (set *Set[E]) Values() []E { 78 values := make([]E, set.Size()) 79 count := 0 80 for item := range set.items { 81 values[count] = item 82 count++ 83 } 84 return values 85 } 86 87 // String returns a string representation of container 88 func (set *Set[E]) String() string { 89 b := strings.Builder{} 90 b.WriteString("HashSet\n") 91 for k := range set.items { 92 b.WriteString(fmt.Sprintf("(key:%v) ", k)) 93 } 94 return b.String() 95 } 96 97 // Intersection returns the intersection between two sets. 98 // The new set consists of all elements that are both in "set" and "another". 99 // Ref: https://en.wikipedia.org/wiki/Intersection_(set_theory) 100 func (set *Set[E]) Intersection(another *Set[E]) *Set[E] { 101 result := New[E]() 102 103 // Iterate over smaller set (optimization) 104 if set.Size() <= another.Size() { 105 for item := range set.items { 106 if _, contains := another.items[item]; contains { 107 result.Add(item) 108 } 109 } 110 } else { 111 for item := range another.items { 112 if _, contains := set.items[item]; contains { 113 result.Add(item) 114 } 115 } 116 } 117 118 return result 119 } 120 121 // Union returns the union of two sets. 122 // The new set consists of all elements that are in "set" or "another" (possibly both). 123 // Ref: https://en.wikipedia.org/wiki/Union_(set_theory) 124 func (set *Set[E]) Union(another *Set[E]) *Set[E] { 125 result := New[E]() 126 127 for item := range set.items { 128 result.Add(item) 129 } 130 for item := range another.items { 131 result.Add(item) 132 } 133 134 return result 135 } 136 137 // Difference returns the difference between two sets. 138 // The new set consists of all elements that are in "set" but not in "another". 139 // Ref: https://proofwiki.org/wiki/Definition:Set_Difference 140 func (set *Set[E]) Difference(another *Set[E]) *Set[E] { 141 result := New[E]() 142 143 for item := range set.items { 144 if _, contains := another.items[item]; !contains { 145 result.Add(item) 146 } 147 } 148 149 return result 150 } 151 152 // UnmarshalJSON @implements json.Unmarshaler 153 func (set *Set[E]) UnmarshalJSON(bytes []byte) error { 154 elements := []E{} 155 err := json.Unmarshal(bytes, &elements) 156 if err == nil { 157 set.Clear() 158 set.Add(elements...) 159 } 160 return err 161 } 162 163 // MarshalJSON @implements json.Marshaler 164 func (set *Set[E]) MarshalJSON() ([]byte, error) { 165 return json.Marshal(set.Values()) 166 }