github.com/m4gshm/gollections@v0.0.10/collection/immutable/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 "github.com/m4gshm/gollections/notsafe" 13 "github.com/m4gshm/gollections/slice" 14 "github.com/m4gshm/gollections/stream" 15 ) 16 17 // WrapSet creates a set using a map and an order slice as the internal storage. 18 func WrapSet[T comparable](order []T, elements map[T]struct{}) Set[T] { 19 return Set[T]{order: order, elements: elements, esize: notsafe.GetTypeSize[T]()} 20 } 21 22 // Set is a collection implementation that provides storage for unique elements, prevents duplication, and guarantees access order. The elements must be comparable. 23 type Set[T comparable] struct { 24 order []T 25 elements map[T]struct{} 26 esize uintptr 27 } 28 29 var ( 30 _ collection.Set[int] = (*Set[int])(nil) 31 _ collection.Set[int] = Set[int]{} 32 _ loop.Looper[int, *slice.Iter[int]] = (*Set[int])(nil) 33 _ loop.Looper[int, *slice.Iter[int]] = Set[int]{} 34 _ fmt.Stringer = (*Set[int])(nil) 35 _ fmt.Stringer = Set[int]{} 36 ) 37 38 // Iter creates an iterator and returns as interface 39 func (s Set[T]) Iter() c.Iterator[T] { 40 h := s.Head() 41 return &h 42 } 43 44 // Loop creates an iterator and returns as implementation type reference 45 func (s Set[T]) Loop() *slice.Iter[T] { 46 h := s.Head() 47 return &h 48 } 49 50 // Head creates an iterator and returns as implementation type value 51 func (s Set[T]) Head() slice.Iter[T] { 52 return slice.NewHeadS(s.order, s.esize) 53 } 54 55 // Tail creates an iterator pointing to the end of the collection 56 func (s Set[T]) Tail() slice.Iter[T] { 57 return slice.NewTailS(s.order, s.esize) 58 } 59 60 // First returns the first element of the collection, an iterator to iterate over the remaining elements, and true\false marker of availability next elements. 61 // If no more elements then ok==false. 62 func (s Set[T]) First() (slice.Iter[T], T, bool) { 63 var ( 64 iterator = slice.NewHeadS(s.order, s.esize) 65 first, ok = iterator.Next() 66 ) 67 return iterator, first, ok 68 } 69 70 // Last returns the latest element of the collection, an iterator to reverse iterate over the remaining elements, and true\false marker of availability previous elements. 71 // If no more elements then ok==false. 72 func (s Set[T]) Last() (slice.Iter[T], T, bool) { 73 var ( 74 iterator = slice.NewTailS(s.order, s.esize) 75 first, ok = iterator.Prev() 76 ) 77 return iterator, first, ok 78 } 79 80 // Slice collects the elements to a slice 81 func (s Set[T]) Slice() []T { 82 return slice.Clone(s.order) 83 } 84 85 // Append collects the values to the specified 'out' slice 86 func (s Set[T]) Append(out []T) []T { 87 return append(out, s.order...) 88 } 89 90 // Len returns amount of elements 91 func (s Set[T]) Len() int { 92 return len(s.order) 93 } 94 95 // IsEmpty returns true if the collection is empty 96 func (s Set[T]) IsEmpty() bool { 97 return s.Len() == 0 98 } 99 100 // For applies the 'walker' function for every element. Return the c.ErrBreak to stop. 101 func (s Set[T]) For(walker func(T) error) error { 102 return slice.For(s.order, walker) 103 } 104 105 // ForEach applies the 'walker' function for every element 106 func (s Set[T]) ForEach(walker func(T)) { 107 slice.ForEach(s.order, walker) 108 } 109 110 // Filter returns a stream consisting of elements that satisfy the condition of the 'predicate' function 111 func (s Set[T]) Filter(predicate func(T) bool) stream.Iter[T] { 112 h := s.Head() 113 return stream.New(loop.Filter(h.Next, predicate).Next) 114 } 115 116 // Filt returns a breakable stream consisting of elements that satisfy the condition of the 'predicate' function 117 func (s Set[T]) Filt(predicate func(T) (bool, error)) breakStream.Iter[T] { 118 h := s.Head() 119 return breakStream.New(breakLoop.Filt(breakLoop.From(h.Next), predicate).Next) 120 } 121 122 // Convert returns a stream that applies the 'converter' function to the collection elements 123 func (s Set[T]) Convert(converter func(T) T) stream.Iter[T] { 124 return collection.Convert(s, converter) 125 } 126 127 // Conv returns a breakable stream that applies the 'converter' function to the collection elements 128 func (s Set[T]) Conv(converter func(T) (T, error)) breakStream.Iter[T] { 129 return collection.Conv(s, converter) 130 } 131 132 // Reduce reduces the elements into an one using the 'merge' function 133 func (s Set[T]) Reduce(merge func(T, T) T) T { 134 return slice.Reduce(s.order, merge) 135 } 136 137 // HasAny finds the first element that satisfies the 'predicate' function condition and returns true if successful 138 func (s Set[T]) HasAny(predicate func(T) bool) bool { 139 return slice.HasAny(s.order, predicate) 140 } 141 142 // Contains checks is the collection contains an element 143 func (s Set[T]) Contains(element T) (ok bool) { 144 if elements := s.elements; elements != nil { 145 _, ok = s.elements[element] 146 } 147 return ok 148 } 149 150 // Sort sorts the elements 151 func (s Set[T]) Sort(less slice.Less[T]) Set[T] { 152 return s.sortBy(sort.Slice, less) 153 } 154 155 // StableSort sorts the elements 156 func (s Set[T]) StableSort(less slice.Less[T]) Set[T] { 157 return s.sortBy(sort.SliceStable, less) 158 } 159 160 func (s Set[T]) sortBy(sorter slice.Sorter, less slice.Less[T]) Set[T] { 161 order := slice.Clone(s.order) 162 slice.Sort(order, sorter, less) 163 return WrapSet(order, s.elements) 164 } 165 166 func (s Set[T]) String() string { 167 return slice.ToString(s.order) 168 } 169 170 func addToSet[T comparable](e T, uniques map[T]struct{}, order []T) []T { 171 if _, ok := uniques[e]; !ok { 172 order = append(order, e) 173 uniques[e] = struct{}{} 174 } 175 return order 176 }