github.com/jxskiss/gopkg/v2@v2.14.9-0.20240514120614-899f3e7952b4/collection/set/generic.go (about) 1 package set 2 3 import "encoding/json" 4 5 // Generic is a generic set collection. 6 // The zero value of Generic is an empty instance ready to use. 7 // A zero Generic set value shall not be copied, or it may result 8 // incorrect behavior. 9 type Generic[T comparable] struct { 10 m map[T]struct{} 11 } 12 13 // New creates a set instance and add the given values into the set. 14 func New[T comparable](vals ...T) Generic[T] { 15 size := max(len(vals), minSize) 16 set := Generic[T]{ 17 m: make(map[T]struct{}, size), 18 } 19 for _, v := range vals { 20 set.m[v] = struct{}{} 21 } 22 return set 23 } 24 25 // NewWithSize creates a set instance with given initial size. 26 func NewWithSize[T comparable](size int) Generic[T] { 27 set := Generic[T]{ 28 m: make(map[T]struct{}, size), 29 } 30 return set 31 } 32 33 // Size returns the size of the set collection. 34 func (s Generic[T]) Size() int { return len(s.m) } 35 36 // Add adds the given values into the set. 37 func (s *Generic[T]) Add(vals ...T) { 38 if s.m == nil { 39 size := max(len(vals), minSize) 40 s.m = make(map[T]struct{}, size) 41 } 42 for _, v := range vals { 43 s.m[v] = struct{}{} 44 } 45 } 46 47 // Delete deletes values from the set. 48 func (s *Generic[T]) Delete(vals ...T) { 49 for _, v := range vals { 50 delete(s.m, v) 51 } 52 } 53 54 // Iterate iterates the set in no particular order and calls the given 55 // function for each set element. 56 func (s Generic[T]) Iterate(fn func(T)) { 57 for val := range s.m { 58 fn(val) 59 } 60 } 61 62 // Contains returns true if the set contains all the values. 63 func (s Generic[T]) Contains(vals ...T) bool { 64 if len(vals) == 0 { 65 return false 66 } 67 for _, v := range vals { 68 if _, ok := s.m[v]; !ok { 69 return false 70 } 71 } 72 return true 73 } 74 75 // ContainsAny returns true if the set contains any of the values. 76 func (s Generic[T]) ContainsAny(vals ...T) bool { 77 for _, v := range vals { 78 if _, ok := s.m[v]; ok { 79 return true 80 } 81 } 82 return false 83 } 84 85 // Diff returns a new set about the values which other set doesn't contain. 86 func (s Generic[T]) Diff(other Generic[T]) Generic[T] { 87 res := NewWithSize[T](s.Size()) 88 89 for val := range s.m { 90 if _, ok := other.m[val]; !ok { 91 res.m[val] = struct{}{} 92 } 93 } 94 return res 95 } 96 97 // DiffSlice is similar to Diff, but takes a slice as parameter. 98 func (s Generic[T]) DiffSlice(other []T) Generic[T] { 99 otherLen := len(other) 100 if len(s.m) > otherLen { 101 tmp := NewWithSize[T](otherLen) 102 dup := 0 103 for i := 0; i < otherLen; i++ { 104 val := other[i] 105 if _, ok := s.m[val]; ok { 106 dup++ 107 } 108 tmp.m[val] = struct{}{} 109 } 110 res := NewWithSize[T](max(s.Size()-dup, 0)) 111 for val := range s.m { 112 if _, ok := tmp.m[val]; !ok { 113 res.m[val] = struct{}{} 114 } 115 } 116 return res 117 } 118 119 res := NewWithSize[T](s.Size()) 120 for val := range s.m { 121 res.m[val] = struct{}{} 122 } 123 for i := 0; i < otherLen; i++ { 124 val := other[i] 125 delete(res.m, val) 126 } 127 return res 128 } 129 130 // FilterContains returns a new slice which contains values that present 131 // in the provided slice and also present in the set. 132 func (s Generic[T]) FilterContains(slice []T) []T { 133 res := make([]T, 0, min(s.Size(), len(slice))) 134 for _, val := range slice { 135 if _, ok := s.m[val]; ok { 136 res = append(res, val) 137 } 138 } 139 return res 140 } 141 142 // FilterNotContains returns a new slice which contains values that present 143 // in the provided slice but don't present in the set. 144 func (s Generic[T]) FilterNotContains(slice []T) []T { 145 res := make([]T, 0, len(slice)) 146 for _, val := range slice { 147 if _, ok := s.m[val]; !ok { 148 res = append(res, val) 149 } 150 } 151 return res 152 } 153 154 // Intersect returns a new set about values which other set also contains. 155 func (s Generic[T]) Intersect(other Generic[T]) Generic[T] { 156 res := NewWithSize[T](min(s.Size(), other.Size())) 157 158 // loop over the smaller set for better performance 159 small, big := s, other 160 if s.Size() > other.Size() { 161 small, big = other, s 162 } 163 for val := range small.m { 164 if _, ok := big.m[val]; ok { 165 res.m[val] = struct{}{} 166 } 167 } 168 return res 169 } 170 171 // IntersectSlice is similar to Intersect, but takes a slice as parameter. 172 func (s Generic[T]) IntersectSlice(other []T) Generic[T] { 173 res := NewWithSize[T](min(s.Size(), len(other))) 174 for _, val := range other { 175 if _, ok := s.m[val]; ok { 176 res.m[val] = struct{}{} 177 } 178 } 179 return res 180 } 181 182 // Union returns a new set about values either in the set or the other set. 183 func (s Generic[T]) Union(other Generic[T]) Generic[T] { 184 res := NewWithSize[T](s.Size() + other.Size()) 185 for val := range s.m { 186 res.m[val] = struct{}{} 187 } 188 for val := range other.m { 189 res.m[val] = struct{}{} 190 } 191 return res 192 } 193 194 // UnionSlice is similar to Union, but takes a slice as parameter. 195 func (s Generic[T]) UnionSlice(other []T) Generic[T] { 196 res := NewWithSize[T](s.Size() + len(other)) 197 for val := range s.m { 198 res.m[val] = struct{}{} 199 } 200 for _, val := range other { 201 res.m[val] = struct{}{} 202 } 203 return res 204 } 205 206 // Slice converts the set into a slice of type []T. 207 func (s Generic[T]) Slice() []T { 208 res := make([]T, 0, len(s.m)) 209 for val := range s.m { 210 res = append(res, val) 211 } 212 return res 213 } 214 215 // Map converts the set into a map of type map[T]bool. 216 func (s Generic[T]) Map() map[T]bool { 217 res := make(map[T]bool, len(s.m)) 218 for val := range s.m { 219 res[val] = true 220 } 221 return res 222 } 223 224 // MarshalJSON implements json.Marshaler interface, the set will be 225 // marshaled as a slice []T. 226 func (s Generic[T]) MarshalJSON() ([]byte, error) { 227 res := s.Slice() 228 return json.Marshal(res) 229 } 230 231 // UnmarshalJSON implements json.Unmarshaler interface, it will unmarshal 232 // a slice []T to the set. 233 func (s *Generic[T]) UnmarshalJSON(b []byte) error { 234 vals := make([]T, 0) 235 err := json.Unmarshal(b, &vals) 236 if err == nil { 237 s.Add(vals...) 238 } 239 return err 240 } 241 242 // MarshalYAML implements yaml.Marshaler interface of the yaml package, 243 // the set will be marshaled as a slice []T. 244 func (s Generic[T]) MarshalYAML() (any, error) { 245 res := s.Slice() 246 return res, nil 247 } 248 249 // UnmarshalYAML implements yaml.Unmarshaler interface of the yaml package, 250 // it will unmarshal a slice []T to the set. 251 func (s *Generic[T]) UnmarshalYAML(unmarshal func(any) error) error { 252 vals := make([]T, 0) 253 err := unmarshal(&vals) 254 if err == nil { 255 s.Add(vals...) 256 } 257 return err 258 }