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

     1  package mutable
     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/collection/mutable/ordered"
    10  	"github.com/m4gshm/gollections/loop"
    11  	"github.com/m4gshm/gollections/map_"
    12  	"github.com/m4gshm/gollections/slice"
    13  )
    14  
    15  // WrapSet creates a set using a map as the internal storage.
    16  func WrapSet[T comparable](elements map[T]struct{}) *Set[T] {
    17  	return &Set[T]{elements: elements}
    18  }
    19  
    20  // Set is a collection implementation that provides element uniqueness. The elements must be comparable.
    21  type Set[T comparable] struct {
    22  	elements map[T]struct{}
    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  	for v := range s.elements {
    39  		if !consumer(v) {
    40  			return
    41  		}
    42  	}
    43  }
    44  
    45  // Loop creates a loop to iterate through the collection.
    46  func (s *Set[T]) Loop() loop.Loop[T] {
    47  	h := s.Head()
    48  	return (&h).Next
    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 map[T]struct{}
    61  	if s != nil {
    62  		elements = s.elements
    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 elements := s.elements; elements != nil {
    82  			out = map_.Keys(elements)
    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 elements := s.elements; elements != nil {
    92  			out = map_.AppendKeys(s.elements, out)
    93  		}
    94  	}
    95  	return out
    96  }
    97  
    98  // Clone returns copy of the collection
    99  func (s *Set[T]) Clone() *Set[T] {
   100  	var elements map[T]struct{}
   101  	if s != nil {
   102  		elements = map_.Clone(s.elements)
   103  	}
   104  	return WrapSet(elements)
   105  }
   106  
   107  // IsEmpty returns true if the collection is empty
   108  func (s *Set[T]) IsEmpty() bool {
   109  	return s.Len() == 0
   110  }
   111  
   112  // Len returns amount of the elements
   113  func (s *Set[T]) Len() int {
   114  	if s == nil {
   115  		return 0
   116  	}
   117  	return len(s.elements)
   118  }
   119  
   120  // Contains checks if the collection contains an element
   121  func (s *Set[T]) Contains(element T) (ok bool) {
   122  	if s != nil {
   123  		_, ok = s.elements[element]
   124  	}
   125  	return ok
   126  }
   127  
   128  // Add adds elements in the collection
   129  func (s *Set[T]) Add(elements ...T) {
   130  	if s != nil {
   131  		for _, element := range elements {
   132  			s.AddOne(element)
   133  		}
   134  	}
   135  }
   136  
   137  // AddOne adds an element in the collection
   138  func (s *Set[T]) AddOne(element T) {
   139  	if s == nil {
   140  		return
   141  	} else if elements := s.elements; elements == nil {
   142  		s.elements = map[T]struct{}{element: {}}
   143  	} else {
   144  		elements[element] = struct{}{}
   145  	}
   146  }
   147  
   148  // AddNew inserts elements if they are not contained in the collection
   149  func (s *Set[T]) AddNew(elements ...T) bool {
   150  	if s == nil {
   151  		return false
   152  	}
   153  	ok := false
   154  	for _, element := range elements {
   155  		ok = s.AddOneNew(element) || ok
   156  	}
   157  	return ok
   158  }
   159  
   160  // AddOneNew inserts an element if it is not contained in the collection
   161  func (s *Set[T]) AddOneNew(element T) (ok bool) {
   162  	if s != nil {
   163  		elements := s.elements
   164  		if elements == nil {
   165  			elements = map[T]struct{}{}
   166  			s.elements = elements
   167  		}
   168  		if ok = !s.Contains(element); ok {
   169  			elements[element] = struct{}{}
   170  		}
   171  	}
   172  	return ok
   173  }
   174  
   175  // AddAll inserts all elements from the "other" collection
   176  func (s *Set[T]) AddAll(elements c.ForEach[T]) {
   177  	if !(s == nil || elements == nil) {
   178  		elements.ForEach(s.AddOne)
   179  	}
   180  }
   181  
   182  // AddAllNew inserts elements from the "other" collection if they are not contained in the collection
   183  func (s *Set[T]) AddAllNew(other c.ForEach[T]) (ok bool) {
   184  	if !(s == nil || other == nil) {
   185  		other.ForEach(func(element T) { ok = s.AddOneNew(element) || ok })
   186  	}
   187  	return ok
   188  }
   189  
   190  // Delete removes elements from the collection
   191  func (s *Set[T]) Delete(elements ...T) {
   192  	if s != nil {
   193  		for _, element := range elements {
   194  			s.DeleteOne(element)
   195  		}
   196  	}
   197  }
   198  
   199  // DeleteOne removes an element from the collection
   200  func (s *Set[T]) DeleteOne(element T) {
   201  	if s != nil {
   202  		delete(s.elements, element)
   203  	}
   204  }
   205  
   206  // DeleteActual removes elements only if they are contained in the collection
   207  func (s *Set[T]) DeleteActual(elements ...T) bool {
   208  	if s == nil {
   209  		return false
   210  	}
   211  	ok := false
   212  	for i := range elements {
   213  		ok = s.DeleteActualOne(elements[i]) || ok
   214  	}
   215  	return ok
   216  }
   217  
   218  // DeleteActualOne removes an element only if it is contained in the collection
   219  func (s *Set[T]) DeleteActualOne(element T) (ok bool) {
   220  	if !(s == nil || s.elements == nil) {
   221  		if _, ok = s.elements[element]; ok {
   222  			delete(s.elements, element)
   223  		}
   224  	}
   225  	return ok
   226  }
   227  
   228  // For applies the 'consumer' function for the elements until the consumer returns the c.Break to stop.
   229  func (s *Set[T]) For(consumer func(T) error) error {
   230  	if s == nil {
   231  		return nil
   232  	}
   233  	return map_.ForKeys(s.elements, consumer)
   234  }
   235  
   236  // ForEach applies the 'consumer' function for every element
   237  func (s *Set[T]) ForEach(consumer func(T)) {
   238  	if s != nil {
   239  		map_.ForEachKey(s.elements, consumer)
   240  	}
   241  }
   242  
   243  // Filter returns a loop consisting of elements that satisfy the condition of the 'predicate' function
   244  func (s *Set[T]) Filter(predicate func(T) bool) loop.Loop[T] {
   245  	return loop.Filter(s.Loop(), predicate)
   246  }
   247  
   248  // Filt returns a breakable loop consisting of elements that satisfy the condition of the 'predicate' function
   249  func (s Set[T]) Filt(predicate func(T) (bool, error)) breakLoop.Loop[T] {
   250  	return loop.Filt(s.Loop(), predicate)
   251  }
   252  
   253  // Convert returns a loop that applies the 'converter' function to the collection elements
   254  func (s *Set[T]) Convert(converter func(T) T) loop.Loop[T] {
   255  	return loop.Convert(s.Loop(), converter)
   256  }
   257  
   258  // Conv returns a breakable loop that applies the 'converter' function to the collection elements
   259  func (s *Set[T]) Conv(converter func(T) (T, error)) breakLoop.Loop[T] {
   260  	return loop.Conv(s.Loop(), converter)
   261  }
   262  
   263  // Reduce reduces the elements into an one using the 'merge' function
   264  func (s *Set[T]) Reduce(merge func(T, T) T) (t T) {
   265  	if s != nil {
   266  		t, _ = map_.Reduce(s.elements, func(t1, t2 T, _, _ struct{}) (t T, out struct{}) {
   267  			return merge(t1, t2), out
   268  		})
   269  	}
   270  	return t
   271  }
   272  
   273  // HasAny finds the first element that satisfies the 'predicate' function condition and returns true if successful
   274  func (s *Set[K]) HasAny(predicate func(K) bool) bool {
   275  	if s != nil {
   276  		return map_.HasAny(s.elements, func(k K, _ struct{}) bool {
   277  			return predicate(k)
   278  		})
   279  	}
   280  	return false
   281  }
   282  
   283  // Sort transforms to the ordered Set contains sorted elements
   284  func (s *Set[T]) Sort(comparer slice.Comparer[T]) *ordered.Set[T] {
   285  	if s != nil {
   286  		return ordered.NewSet(slice.Sort(s.Slice(), comparer)...)
   287  	}
   288  	return nil
   289  }
   290  
   291  // StableSort transforms to the ordered Set contains sorted elements
   292  func (s *Set[T]) StableSort(comparer slice.Comparer[T]) *ordered.Set[T] {
   293  	if s != nil {
   294  		return ordered.NewSet(slice.StableSort(s.Slice(), comparer)...)
   295  	}
   296  	return nil
   297  }
   298  
   299  func (s *Set[T]) String() string {
   300  	return slice.ToString(s.Slice())
   301  }