github.com/kaydxh/golang@v0.0.131/go/container/set/set.go (about) 1 /* 2 *Copyright (c) 2022, kaydxh 3 * 4 *Permission is hereby granted, free of charge, to any person obtaining a copy 5 *of this software and associated documentation files (the "Software"), to deal 6 *in the Software without restriction, including without limitation the rights 7 *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 *copies of the Software, and to permit persons to whom the Software is 9 *furnished to do so, subject to the following conditions: 10 * 11 *The above copyright notice and this permission notice shall be included in all 12 *copies or substantial portions of the Software. 13 * 14 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 *SOFTWARE. 21 */ 22 package set 23 24 import ( 25 "encoding/json" 26 "sort" 27 ) 28 29 // type Set[type T comparable] map[T]Empty 30 type Set[T comparable] map[T]Empty 31 32 func New[T comparable](items ...T) Set[T] { 33 // func New[T comparable]() Set[T] { 34 ss := make(Set[T], len(items)) 35 ss.Insert(items...) 36 return ss 37 } 38 39 // Insert adds items to the set. 40 func (s Set[T]) Insert(items ...T) Set[T] { 41 for _, item := range items { 42 s[item] = Empty{} 43 } 44 45 return s 46 } 47 48 // Delete removes all items from the set. 49 func (s Set[T]) Delete(items ...T) Set[T] { 50 for _, item := range items { 51 delete(s, item) 52 } 53 return s 54 } 55 56 // Has returns true if and only if item is contained in the set. 57 func (s Set[T]) Has(item T) bool { 58 _, contained := s[item] 59 return contained 60 } 61 62 // HasAll returns true if and only if all items are contained in the set. 63 func (s Set[T]) HasAll(items ...T) bool { 64 for _, item := range items { 65 if !s.Has(item) { 66 return false 67 } 68 } 69 return true 70 } 71 72 // HasAny returns true if any items are contained in the set. 73 func (s Set[T]) HasAny(items ...T) bool { 74 for _, item := range items { 75 if s.Has(item) { 76 return true 77 } 78 } 79 return false 80 } 81 82 // Difference returns a set of objects that are not in s2 83 // For example: 84 // s1 = {a1, a2, a3} 85 // s2 = {a1, a2, a4, a5} 86 // s1.Difference(s2) = {a3} 87 // s2.Difference(s1) = {a4, a5} 88 func (s Set[T]) Difference(s2 Set[T]) Set[T] { 89 result := New[T]() 90 for key := range s { 91 if !s2.Has(key) { 92 result.Insert(key) 93 } 94 } 95 return result 96 } 97 98 // Union returns a new set which includes items in either s1 or s2. 99 // For example: 100 // s1 = {a1, a2} 101 // s2 = {a3, a4} 102 // s1.Union(s2) = {a1, a2, a3, a4} 103 // s2.Union(s1) = {a1, a2, a3, a4} 104 func (s1 Set[T]) Union(s2 Set[T]) Set[T] { 105 result := New[T]() 106 for key := range s1 { 107 result.Insert(key) 108 } 109 for key := range s2 { 110 result.Insert(key) 111 } 112 return result 113 } 114 115 // Intersection returns a new set which includes the item in BOTH s1 and s2 116 // For example: 117 // s1 = {a1, a2} 118 // s2 = {a2, a3} 119 // s1.Intersection(s2) = {a2} 120 func (s1 Set[T]) Intersection(s2 Set[T]) Set[T] { 121 var walk, other Set[T] 122 result := New[T]() 123 if s1.Len() < s2.Len() { 124 walk = s1 125 other = s2 126 } else { 127 walk = s2 128 other = s1 129 } 130 for key := range walk { 131 if other.Has(key) { 132 result.Insert(key) 133 } 134 } 135 return result 136 } 137 138 // IsSuperset returns true if and only if s1 is a superset of s2. 139 func (s1 Set[T]) IsSuperset(s2 Set[T]) bool { 140 for item := range s2 { 141 if !s1.Has(item) { 142 return false 143 } 144 } 145 return true 146 } 147 148 // Equal returns true if and only if s1 is equal (as a set) to s2. 149 // Two sets are equal if their membership is identical. 150 // (In practice, this means same elements, order doesn't matter) 151 func (s1 Set[T]) Equal(s2 Set[T]) bool { 152 return len(s1) == len(s2) && s1.IsSuperset(s2) 153 } 154 155 type sortableSliceOfT[T comparable] []T 156 157 func (s sortableSliceOfT[T]) Len() int { return len(s) } 158 func (s sortableSliceOfT[T]) Less(i, j int) bool { return lessT(s[i], s[j]) } 159 func (s sortableSliceOfT[T]) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 160 161 // List returns the contents as a sorted Object slice. 162 func (s Set[T]) List() []T { 163 res := make(sortableSliceOfT[T], 0, len(s)) 164 for key := range s { 165 res = append(res, key) 166 } 167 sort.Sort(res) 168 return []T(res) 169 } 170 171 // UnsortedList returns the slice with contents in random order. 172 func (s Set[T]) UnsortedList() []T { 173 res := make([]T, 0, len(s)) 174 for key := range s { 175 res = append(res, key) 176 } 177 return res 178 } 179 180 // Returns a single element from the set. 181 func (s Set[T]) PopAny() (T, bool) { 182 for key := range s { 183 s.Delete(key) 184 return key, true 185 } 186 var zeroValue T 187 return zeroValue, false 188 } 189 190 // Len returns the size of the set. 191 func (s Set[T]) Len() int { 192 return len(s) 193 } 194 195 type LesserT[T comparable] interface { 196 Less(a, b T) bool 197 } 198 199 func lessT[T comparable](lhs, rhs T) bool { 200 jbl, err := json.Marshal(lhs) 201 if err != nil { 202 return false 203 } 204 jbr, err := json.Marshal(rhs) 205 if err != nil { 206 return false 207 } 208 209 return string(jbl) < string(jbr) 210 }