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  }