github.com/m4gshm/gollections@v0.0.13-0.20240331203319-a34a86e58a24/collection/mutable/ordered/set.go (about) 1 package ordered 2 3 import ( 4 "fmt" 5 6 breakLoop "github.com/m4gshm/gollections/break/loop" 7 "github.com/m4gshm/gollections/c" 8 "github.com/m4gshm/gollections/collection" 9 "github.com/m4gshm/gollections/loop" 10 "github.com/m4gshm/gollections/map_" 11 "github.com/m4gshm/gollections/slice" 12 ) 13 14 // WrapSet creates a set using a map and an order slice as the internal storage. 15 func WrapSet[T comparable](elements []T, uniques map[T]int) *Set[T] { 16 return &Set[T]{order: &elements, elements: uniques} 17 } 18 19 // Set is a collection implementation that provides element uniqueness and access order. Elements must be comparable. 20 type Set[T comparable] struct { 21 order *[]T 22 elements map[T]int 23 } 24 25 var ( 26 _ c.Addable[int] = (*Set[int])(nil) 27 _ c.AddableNew[int] = (*Set[int])(nil) 28 _ c.AddableAll[c.ForEach[int]] = (*Set[int])(nil) 29 _ c.AddableAllNew[c.ForEach[int]] = (*Set[int])(nil) 30 _ c.Deleteable[int] = (*Set[int])(nil) 31 _ c.DeleteableVerify[int] = (*Set[int])(nil) 32 _ collection.Set[int] = (*Set[int])(nil) 33 _ fmt.Stringer = (*Set[int])(nil) 34 ) 35 36 // All is used to iterate through the collection using `for ... range`. Supported since go 1.22 with GOEXPERIMENT=rangefunc enabled. 37 func (s *Set[T]) All(consumer func(T) bool) { 38 if s != nil { 39 slice.WalkWhile(*s.order, consumer) 40 } 41 } 42 43 // Loop creates a loop to iterate through the collection. 44 func (s *Set[T]) Loop() loop.Loop[T] { 45 if s == nil { 46 return nil 47 } 48 return loop.Of((*s.order)...) 49 } 50 51 // IterEdit creates iterator that can delete iterable elements 52 func (s *Set[T]) IterEdit() c.DelIterator[T] { 53 h := s.Head() 54 return &h 55 } 56 57 // Deprecated: Head is deprecated. Will be replaced by rance-over function iterator. 58 // Head creates an iterator to iterate through the collection. 59 func (s *Set[T]) Head() SetIter[T] { 60 var elements *[]T 61 if s != nil { 62 elements = s.order 63 } 64 return NewSetIter(elements, s.DeleteOne) 65 } 66 67 // Deprecated: First is deprecated. Will be replaced by rance-over function iterator. 68 // First returns the first element of the collection, an iterator to iterate over the remaining elements, and true\false marker of availability next elements. 69 // If no more elements then ok==false. 70 func (s *Set[T]) First() (SetIter[T], T, bool) { 71 var ( 72 iterator = s.Head() 73 first, ok = iterator.Next() 74 ) 75 return iterator, first, ok 76 } 77 78 // Slice collects the elements to a slice 79 func (s *Set[T]) Slice() (out []T) { 80 if s != nil { 81 if order := s.order; order != nil { 82 out = slice.Clone(*s.order) 83 } 84 } 85 return out 86 } 87 88 // Append collects the values to the specified 'out' slice 89 func (s *Set[T]) Append(out []T) []T { 90 if s != nil { 91 if order := s.order; order != nil { 92 out = append(out, (*s.order)...) 93 } 94 } 95 return out 96 } 97 98 // Clone returns copy of the collection 99 func (s *Set[T]) Clone() *Set[T] { 100 var ( 101 elements []T 102 uniques map[T]int 103 ) 104 if s != nil { 105 if order := s.order; order != nil { 106 elements = slice.Clone(*s.order) 107 } 108 uniques = map_.Clone(s.elements) 109 } 110 return WrapSet(elements, uniques) 111 } 112 113 // IsEmpty returns true if the collection is empty 114 func (s *Set[T]) IsEmpty() bool { 115 return s.Len() == 0 116 } 117 118 // Len returns amount of the elements 119 func (s *Set[T]) Len() int { 120 if s == nil { 121 return 0 122 } 123 if order := s.order; order != nil { 124 return len(*s.order) 125 } 126 return 0 127 } 128 129 // Contains checks if the collection contains an element 130 func (s *Set[T]) Contains(element T) (ok bool) { 131 if s != nil { 132 _, ok = s.elements[element] 133 } 134 return ok 135 } 136 137 // Add adds elements in the collection 138 func (s *Set[T]) Add(elements ...T) { 139 s.AddNew(elements...) 140 } 141 142 // AddOne adds an element in the collection 143 func (s *Set[T]) AddOne(element T) { 144 s.AddOneNew(element) 145 } 146 147 // AddNew inserts elements if they are not contained in the collection 148 func (s *Set[T]) AddNew(elements ...T) bool { 149 if s == nil { 150 return false 151 } 152 ok := false 153 for _, element := range elements { 154 ok = s.AddOneNew(element) || ok 155 } 156 return ok 157 } 158 159 // AddOneNew inserts an element if it is not contained in the collection 160 func (s *Set[T]) AddOneNew(element T) (ok bool) { 161 if s != nil { 162 elements := s.elements 163 if elements == nil { 164 elements = map[T]int{} 165 s.elements = elements 166 s.order = &[]T{} 167 } 168 if ok = !s.Contains(element); ok { 169 order := s.order 170 if order != nil { 171 elements[element] = len(*order) 172 *(s.order) = append(*order, element) 173 } 174 } 175 } 176 return ok 177 } 178 179 // AddAll inserts all elements from the "other" collection 180 func (s *Set[T]) AddAll(other c.ForEach[T]) { 181 if !(s == nil || other == nil) { 182 other.ForEach(s.AddOne) 183 } 184 } 185 186 // AddAllNew inserts elements from the "other" collection if they are not contained in the collection 187 func (s *Set[T]) AddAllNew(other c.ForEach[T]) (ok bool) { 188 if !(s == nil || other == nil) { 189 other.ForEach(func(v T) { ok = s.AddOneNew(v) || ok }) 190 } 191 return ok 192 } 193 194 // Delete removes elements from the collection 195 func (s *Set[T]) Delete(elements ...T) { 196 s.DeleteActual(elements...) 197 } 198 199 // DeleteOne removes an element from the collection 200 func (s *Set[T]) DeleteOne(v T) { 201 s.DeleteActualOne(v) 202 } 203 204 // DeleteActual removes elements only if they are contained in the collection 205 func (s *Set[T]) DeleteActual(elements ...T) bool { 206 if s == nil { 207 return false 208 } 209 ok := false 210 for i := range elements { 211 ok = s.DeleteActualOne(elements[i]) || ok 212 } 213 return ok 214 } 215 216 // DeleteActualOne removes an element only if it is contained in the collection 217 func (s *Set[T]) DeleteActualOne(element T) bool { 218 if !(s == nil || s.elements == nil) { 219 elements := s.elements 220 if pos, ok := elements[element]; ok { 221 delete(elements, element) 222 //todo: need optimize 223 order := s.order 224 ne := slice.Delete(*order, pos) 225 for i := pos; i < len(ne); i++ { 226 elements[ne[i]]-- 227 } 228 *(s.order) = ne 229 return true 230 } 231 } 232 return false 233 } 234 235 // For applies the 'consumer' function for the elements until the consumer returns the c.Break to stop. 236 func (s *Set[T]) For(consumer func(T) error) error { 237 if s == nil { 238 return nil 239 } 240 order := s.order 241 if order == nil { 242 return nil 243 } 244 return slice.For(*order, consumer) 245 } 246 247 // ForEach applies the 'consumer' function for every element 248 func (s *Set[T]) ForEach(consumer func(T)) { 249 if s != nil { 250 if order := s.order; order != nil { 251 slice.ForEach(*order, consumer) 252 } 253 } 254 } 255 256 // Filter returns a loop consisting of elements that satisfy the condition of the 'predicate' function 257 func (s *Set[T]) Filter(predicate func(T) bool) loop.Loop[T] { 258 h := s.Head() 259 return loop.Filter(h.Next, predicate) 260 } 261 262 // Filt returns a breakable loop consisting of elements that satisfy the condition of the 'predicate' function 263 func (s *Set[T]) Filt(predicate func(T) (bool, error)) breakLoop.Loop[T] { 264 return loop.Filt(s.Loop(), predicate) 265 } 266 267 // Convert returns a loop that applies the 'converter' function to the collection elements 268 func (s *Set[T]) Convert(converter func(T) T) loop.Loop[T] { 269 return loop.Convert(s.Loop(), converter) 270 } 271 272 // Conv returns a breakable loop that applies the 'converter' function to the collection elements 273 func (s *Set[T]) Conv(converter func(T) (T, error)) breakLoop.Loop[T] { 274 return loop.Conv(s.Loop(), converter) 275 } 276 277 // Reduce reduces the elements into an one using the 'merge' function 278 func (s *Set[T]) Reduce(merge func(T, T) T) (t T) { 279 if s != nil { 280 if order := s.order; order != nil { 281 t = slice.Reduce(*order, merge) 282 } 283 } 284 return t 285 } 286 287 // HasAny finds the first element that satisfies the 'predicate' function condition and returns true if successful 288 func (s *Set[K]) HasAny(predicate func(K) bool) bool { 289 if s != nil { 290 if order := s.order; order != nil { 291 return slice.HasAny(*order, predicate) 292 } 293 } 294 return false 295 } 296 297 // Sort sorts the elements 298 func (s *Set[T]) Sort(comparer slice.Comparer[T]) *Set[T] { 299 return s.sortBy(slice.Sort, comparer) 300 } 301 302 // StableSort sorts the elements 303 func (s *Set[T]) StableSort(comparer slice.Comparer[T]) *Set[T] { 304 return s.sortBy(slice.StableSort, comparer) 305 } 306 307 func (s *Set[T]) sortBy(sorter func([]T, slice.Comparer[T]) []T, comparer slice.Comparer[T]) *Set[T] { 308 if s != nil { 309 if order := s.order; order != nil { 310 sorter(*order, comparer) 311 for i, v := range *order { 312 s.elements[v] = i 313 } 314 } 315 } 316 return s 317 } 318 319 func (s *Set[T]) String() string { 320 var elements []T 321 if s != nil { 322 if order := s.order; order != nil { 323 elements = *order 324 } 325 } 326 return slice.ToString(elements) 327 } 328 329 func addToSet[T comparable](e T, uniques map[T]int, order []T, pos int) ([]T, int) { 330 if _, ok := uniques[e]; !ok { 331 order = append(order, e) 332 uniques[e] = pos 333 pos++ 334 } 335 return order, pos 336 }