github.com/m4gshm/gollections@v0.0.13-0.20240331203319-a34a86e58a24/collection/immutable/set.go (about)

     1  package immutable
     2  
     3  import (
     4  	"fmt"
     5  
     6  	breakLoop "github.com/m4gshm/gollections/break/loop"
     7  	"github.com/m4gshm/gollections/collection"
     8  	"github.com/m4gshm/gollections/collection/immutable/ordered"
     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 as the internal storage.
    15  func WrapSet[T comparable](elements map[T]struct{}) Set[T] {
    16  	return Set[T]{elements: elements}
    17  }
    18  
    19  // Set is a collection implementation that provides storage for unique elements, prevents duplication. The elements must be comparable.
    20  type Set[T comparable] struct {
    21  	elements map[T]struct{}
    22  }
    23  
    24  var (
    25  	_ collection.Set[int] = (*Set[int])(nil)
    26  	_ collection.Set[int] = Set[int]{}
    27  	_ fmt.Stringer        = (*Set[int])(nil)
    28  	_ fmt.Stringer        = Set[int]{}
    29  )
    30  
    31  // All is used to iterate through the collection using `for ... range`. Supported since go 1.22 with GOEXPERIMENT=rangefunc enabled.
    32  func (s Set[T]) All(consumer func(T) bool) {
    33  	map_.TrackKeysWhile(s.elements, consumer)
    34  }
    35  
    36  // Loop creates a loop to iterate through the collection.
    37  func (s Set[T]) Loop() loop.Loop[T] {
    38  	h := s.Head()
    39  	return (&h).Next
    40  }
    41  
    42  // Deprecated: Head is deprecated. Will be replaced by rance-over function iterator.
    43  // Head creates an iterator to iterate through the collection.
    44  func (s Set[T]) Head() map_.KeyIter[T, struct{}] {
    45  	return map_.NewKeyIter(s.elements)
    46  }
    47  
    48  // Deprecated: First is deprecated. Will be replaced by rance-over function iterator.
    49  // First returns the first element of the collection, an iterator to iterate over the remaining elements, and true\false marker of availability next elements.
    50  // If no more elements then ok==false.
    51  func (s Set[T]) First() (map_.KeyIter[T, struct{}], T, bool) {
    52  	var (
    53  		iterator  = s.Head()
    54  		first, ok = iterator.Next()
    55  	)
    56  	return iterator, first, ok
    57  }
    58  
    59  // Slice collects the elements to a slice
    60  func (s Set[T]) Slice() []T {
    61  	return map_.Keys(s.elements)
    62  }
    63  
    64  // Append collects the values to the specified 'out' slice
    65  func (s Set[T]) Append(out []T) []T {
    66  	return map_.AppendKeys(s.elements, out)
    67  }
    68  
    69  // Len returns amount of elements
    70  func (s Set[T]) Len() int {
    71  	return len(s.elements)
    72  }
    73  
    74  // IsEmpty returns true if the collection is empty
    75  func (s Set[T]) IsEmpty() bool {
    76  	return s.Len() == 0
    77  }
    78  
    79  // For applies the 'consumer' function for the elements until the consumer returns the c.Break to stop.
    80  func (s Set[T]) For(consumer func(T) error) error {
    81  
    82  	return map_.ForKeys(s.elements, consumer)
    83  }
    84  
    85  // ForEach applies the 'consumer' function for every element
    86  func (s Set[T]) ForEach(consumer func(T)) {
    87  	map_.ForEachKey(s.elements, consumer)
    88  }
    89  
    90  // Filter returns a loop consisting of elements that satisfy the condition of the 'predicate' function
    91  func (s Set[T]) Filter(predicate func(T) bool) loop.Loop[T] {
    92  	return loop.Filter(s.Loop(), predicate)
    93  }
    94  
    95  // Filt returns a breakable loop consisting of elements that satisfy the condition of the 'predicate' function
    96  func (s Set[T]) Filt(predicate func(T) (bool, error)) breakLoop.Loop[T] {
    97  	return loop.Filt(s.Loop(), predicate)
    98  }
    99  
   100  // Convert returns a loop that applies the 'converter' function to the collection elements
   101  func (s Set[T]) Convert(converter func(T) T) loop.Loop[T] {
   102  	return loop.Convert(s.Loop(), converter)
   103  }
   104  
   105  // Conv returns a breakable loop that applies the 'converter' function to the collection elements
   106  func (s Set[T]) Conv(converter func(T) (T, error)) breakLoop.Loop[T] {
   107  	return loop.Conv(s.Loop(), converter)
   108  }
   109  
   110  // Reduce reduces the elements into an one using the 'merge' function
   111  func (s Set[T]) Reduce(merge func(T, T) T) T {
   112  	t, _ := map_.Reduce(s.elements, func(t1, t2 T, _, _ struct{}) (t T, out struct{}) {
   113  		return merge(t1, t2), out
   114  	})
   115  	return t
   116  }
   117  
   118  // HasAny finds the first element that satisfies the 'predicate' function condition and returns true if successful
   119  func (s Set[T]) HasAny(predicate func(T) bool) bool {
   120  	return map_.HasAny(s.elements, func(t T, _ struct{}) bool {
   121  		return predicate(t)
   122  	})
   123  }
   124  
   125  // Contains checks is the collection contains an element
   126  func (s Set[T]) Contains(element T) (ok bool) {
   127  	if elements := s.elements; elements != nil {
   128  		_, ok = elements[element]
   129  	}
   130  	return ok
   131  }
   132  
   133  // Sort transforms to the ordered set with sorted elements
   134  func (s Set[T]) Sort(comparer slice.Comparer[T]) ordered.Set[T] {
   135  	return s.sortBy(slice.Sort, comparer)
   136  }
   137  
   138  // StableSort transforms to the ordered set with sorted elements
   139  func (s Set[T]) StableSort(comparer slice.Comparer[T]) ordered.Set[T] {
   140  	return s.sortBy(slice.StableSort, comparer)
   141  }
   142  
   143  func (s Set[T]) sortBy(sorter func([]T, slice.Comparer[T]) []T, comparer slice.Comparer[T]) ordered.Set[T] {
   144  	return ordered.WrapSet(sorter(s.Slice(), comparer), s.elements)
   145  }
   146  
   147  func (s Set[T]) String() string {
   148  	return slice.ToString(s.Slice())
   149  }