github.com/m4gshm/gollections@v0.0.10/collection/mutable/ordered/set.go (about) 1 package ordered 2 3 import ( 4 "fmt" 5 "sort" 6 7 breakLoop "github.com/m4gshm/gollections/break/loop" 8 breakStream "github.com/m4gshm/gollections/break/stream" 9 "github.com/m4gshm/gollections/c" 10 "github.com/m4gshm/gollections/collection" 11 "github.com/m4gshm/gollections/loop" 12 iter "github.com/m4gshm/gollections/loop" 13 "github.com/m4gshm/gollections/map_" 14 "github.com/m4gshm/gollections/slice" 15 "github.com/m4gshm/gollections/stream" 16 ) 17 18 // WrapSet creates a set using a map and an order slice as the internal storage. 19 func WrapSet[T comparable](elements []T, uniques map[T]int) *Set[T] { 20 return &Set[T]{order: &elements, elements: uniques} 21 } 22 23 // Set is a collection implementation that provides element uniqueness and access order. Elements must be comparable. 24 type Set[T comparable] struct { 25 order *[]T 26 elements map[T]int 27 } 28 29 var ( 30 _ c.Addable[int] = (*Set[int])(nil) 31 _ c.AddableNew[int] = (*Set[int])(nil) 32 _ c.AddableAll[c.ForEachLoop[int]] = (*Set[int])(nil) 33 _ c.AddableAllNew[c.ForEachLoop[int]] = (*Set[int])(nil) 34 _ c.Deleteable[int] = (*Set[int])(nil) 35 _ c.DeleteableVerify[int] = (*Set[int])(nil) 36 _ collection.Set[int] = (*Set[int])(nil) 37 _ loop.Looper[int, *SetIter[int]] = (*Set[int])(nil) 38 _ fmt.Stringer = (*Set[int])(nil) 39 ) 40 41 // Iter creates an iterator and returns as interface 42 func (s *Set[T]) Iter() c.Iterator[T] { 43 h := s.Head() 44 return &h 45 } 46 47 // Loop creates an iterator and returns as implementation type reference 48 func (s *Set[T]) Loop() *SetIter[T] { 49 h := s.Head() 50 return &h 51 } 52 53 // IterEdit creates iterator that can delete iterable elements 54 func (s *Set[T]) IterEdit() c.DelIterator[T] { 55 h := s.Head() 56 return &h 57 } 58 59 // Head creates an iterator and returns as implementation type value 60 func (s *Set[T]) Head() SetIter[T] { 61 var elements *[]T 62 if s != nil { 63 elements = s.order 64 } 65 return NewSetIter(elements, s.DeleteOne) 66 } 67 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.ForEachLoop[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.ForEachLoop[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(pos, *order) 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 'walker' function for the elements. Return the c.ErrBreak to stop. 236 func (s *Set[T]) For(walker 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, walker) 245 } 246 247 // ForEach applies the 'walker' function for every element 248 func (s *Set[T]) ForEach(walker func(T)) { 249 if s != nil { 250 if order := s.order; order != nil { 251 slice.ForEach(*order, walker) 252 } 253 } 254 } 255 256 // Filter returns a stream consisting of elements that satisfy the condition of the 'predicate' function 257 func (s *Set[T]) Filter(predicate func(T) bool) stream.Iter[T] { 258 h := s.Head() 259 return stream.New(iter.Filter(h.Next, predicate).Next) 260 } 261 262 // Filt returns a breakable stream consisting of elements that satisfy the condition of the 'predicate' function 263 func (s *Set[T]) Filt(predicate func(T) (bool, error)) breakStream.Iter[T] { 264 h := s.Head() 265 return breakStream.New(breakLoop.Filt(breakLoop.From(h.Next), predicate).Next) 266 } 267 268 // Convert returns a stream that applies the 'converter' function to the collection elements 269 func (s *Set[T]) Convert(converter func(T) T) stream.Iter[T] { 270 return collection.Convert(s, converter) 271 } 272 273 // Conv returns a breakable stream that applies the 'converter' function to the collection elements 274 func (s *Set[T]) Conv(converter func(T) (T, error)) breakStream.Iter[T] { 275 return collection.Conv(s, converter) 276 } 277 278 // Reduce reduces the elements into an one using the 'merge' function 279 func (s *Set[T]) Reduce(merge func(T, T) T) (t T) { 280 if s != nil { 281 if order := s.order; order != nil { 282 t = slice.Reduce(*order, merge) 283 } 284 } 285 return t 286 } 287 288 // HasAny finds the first element that satisfies the 'predicate' function condition and returns true if successful 289 func (s *Set[K]) HasAny(predicate func(K) bool) bool { 290 if s != nil { 291 if order := s.order; order != nil { 292 return slice.HasAny(*order, predicate) 293 } 294 } 295 return false 296 } 297 298 // Sort sorts the elements 299 func (s *Set[T]) Sort(less slice.Less[T]) *Set[T] { 300 return s.sortBy(sort.Slice, less) 301 } 302 303 // StableSort sorts the elements 304 func (s *Set[T]) StableSort(less slice.Less[T]) *Set[T] { 305 return s.sortBy(sort.SliceStable, less) 306 } 307 308 func (s *Set[T]) sortBy(sorter slice.Sorter, less slice.Less[T]) *Set[T] { 309 if s != nil { 310 if order := s.order; order != nil { 311 slice.Sort(*order, sorter, less) 312 } 313 } 314 return s 315 } 316 317 func (s *Set[T]) String() string { 318 var elements []T 319 if s != nil { 320 if order := s.order; order != nil { 321 elements = *order 322 } 323 } 324 return slice.ToString(elements) 325 } 326 327 func addToSet[T comparable](e T, uniques map[T]int, order []T, pos int) ([]T, int) { 328 if _, ok := uniques[e]; !ok { 329 order = append(order, e) 330 uniques[e] = pos 331 pos++ 332 } 333 return order, pos 334 }