github.com/m4gshm/gollections@v0.0.10/collection/mutable/set.go (about)

     1  package mutable
     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/collection/mutable/ordered"
    12  	"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 as the internal storage.
    19  func WrapSet[T comparable](elements map[T]struct{}) *Set[T] {
    20  	return &Set[T]{elements: elements}
    21  }
    22  
    23  // Set is a collection implementation that provides element uniqueness. The elements must be comparable.
    24  type Set[T comparable] struct {
    25  	elements map[T]struct{}
    26  }
    27  
    28  var (
    29  	_ c.Addable[int]                      = (*Set[int])(nil)
    30  	_ c.AddableNew[int]                   = (*Set[int])(nil)
    31  	_ c.AddableAll[c.ForEachLoop[int]]    = (*Set[int])(nil)
    32  	_ c.AddableAllNew[c.ForEachLoop[int]] = (*Set[int])(nil)
    33  	_ c.Deleteable[int]                   = (*Set[int])(nil)
    34  	_ c.DeleteableVerify[int]             = (*Set[int])(nil)
    35  	_ collection.Set[int]                 = (*Set[int])(nil)
    36  	_ loop.Looper[int, *SetIter[int]]     = (*Set[int])(nil)
    37  	_ fmt.Stringer                        = (*Set[int])(nil)
    38  )
    39  
    40  // Iter creates an iterator and returns as interface
    41  func (s *Set[T]) Iter() c.Iterator[T] {
    42  	h := s.Head()
    43  	return &h
    44  }
    45  
    46  // Loop creates an iterator and returns as implementation type reference
    47  func (s *Set[T]) Loop() *SetIter[T] {
    48  	h := s.Head()
    49  	return &h
    50  }
    51  
    52  // IterEdit creates iterator that can delete iterable elements
    53  func (s *Set[T]) IterEdit() c.DelIterator[T] {
    54  	h := s.Head()
    55  	return &h
    56  }
    57  
    58  // Head creates an iterator and returns as implementation type value
    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  // First returns the first element of the collection, an iterator to iterate over the remaining elements, and true\false marker of availability next elements.
    68  // If no more elements then ok==false.
    69  func (s *Set[T]) First() (SetIter[T], T, bool) {
    70  	var (
    71  		iterator  = s.Head()
    72  		first, ok = iterator.Next()
    73  	)
    74  	return iterator, first, ok
    75  }
    76  
    77  // Slice collects the elements to a slice
    78  func (s *Set[T]) Slice() (out []T) {
    79  	if s != nil {
    80  		if elements := s.elements; elements != nil {
    81  			out = map_.Keys(elements)
    82  		}
    83  	}
    84  	return out
    85  }
    86  
    87  // Append collects the values to the specified 'out' slice
    88  func (s *Set[T]) Append(out []T) []T {
    89  	if s != nil {
    90  		if elements := s.elements; elements != nil {
    91  			out = map_.AppendKeys(s.elements, out)
    92  		}
    93  	}
    94  	return out
    95  }
    96  
    97  // Clone returns copy of the collection
    98  func (s *Set[T]) Clone() *Set[T] {
    99  	var elements map[T]struct{}
   100  	if s != nil {
   101  		elements = map_.Clone(s.elements)
   102  	}
   103  	return WrapSet(elements)
   104  }
   105  
   106  // IsEmpty returns true if the collection is empty
   107  func (s *Set[T]) IsEmpty() bool {
   108  	return s.Len() == 0
   109  }
   110  
   111  // Len returns amount of the elements
   112  func (s *Set[T]) Len() int {
   113  	if s == nil {
   114  		return 0
   115  	}
   116  	return len(s.elements)
   117  }
   118  
   119  // Contains checks if the collection contains an element
   120  func (s *Set[T]) Contains(element T) (ok bool) {
   121  	if s != nil {
   122  		_, ok = s.elements[element]
   123  	}
   124  	return ok
   125  }
   126  
   127  // Add adds elements in the collection
   128  func (s *Set[T]) Add(elements ...T) {
   129  	if s != nil {
   130  		for _, element := range elements {
   131  			s.AddOne(element)
   132  		}
   133  	}
   134  }
   135  
   136  // AddOne adds an element in the collection
   137  func (s *Set[T]) AddOne(element T) {
   138  	if s == nil {
   139  		return
   140  	} else if elements := s.elements; elements == nil {
   141  		s.elements = map[T]struct{}{element: {}}
   142  	} else {
   143  		elements[element] = struct{}{}
   144  	}
   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]struct{}{}
   165  			s.elements = elements
   166  		}
   167  		if ok = !s.Contains(element); ok {
   168  			elements[element] = struct{}{}
   169  		}
   170  	}
   171  	return ok
   172  }
   173  
   174  // AddAll inserts all elements from the "other" collection
   175  func (s *Set[T]) AddAll(elements c.ForEachLoop[T]) {
   176  	if !(s == nil || elements == nil) {
   177  		elements.ForEach(s.AddOne)
   178  	}
   179  }
   180  
   181  // AddAllNew inserts elements from the "other" collection if they are not contained in the collection
   182  func (s *Set[T]) AddAllNew(other c.ForEachLoop[T]) (ok bool) {
   183  	if !(s == nil || other == nil) {
   184  		other.ForEach(func(element T) { ok = s.AddOneNew(element) || ok })
   185  	}
   186  	return ok
   187  }
   188  
   189  // Delete removes elements from the collection
   190  func (s *Set[T]) Delete(elements ...T) {
   191  	if s != nil {
   192  		for _, element := range elements {
   193  			s.DeleteOne(element)
   194  		}
   195  	}
   196  }
   197  
   198  // DeleteOne removes an element from the collection
   199  func (s *Set[T]) DeleteOne(element T) {
   200  	if s != nil {
   201  		delete(s.elements, element)
   202  	}
   203  }
   204  
   205  // DeleteActual removes elements only if they are contained in the collection
   206  func (s *Set[T]) DeleteActual(elements ...T) bool {
   207  	if s == nil {
   208  		return false
   209  	}
   210  	ok := false
   211  	for i := range elements {
   212  		ok = s.DeleteActualOne(elements[i]) || ok
   213  	}
   214  	return ok
   215  }
   216  
   217  // DeleteActualOne removes an element only if it is contained in the collection
   218  func (s *Set[T]) DeleteActualOne(element T) (ok bool) {
   219  	if !(s == nil || s.elements == nil) {
   220  		if _, ok = s.elements[element]; ok {
   221  			delete(s.elements, element)
   222  		}
   223  	}
   224  	return ok
   225  }
   226  
   227  // For applies the 'walker' function for the elements. Return the c.ErrBreak to stop.
   228  func (s *Set[T]) For(walker func(T) error) error {
   229  	if s == nil {
   230  		return nil
   231  	}
   232  	return map_.ForKeys(s.elements, walker)
   233  }
   234  
   235  // ForEach applies the 'walker' function for every element
   236  func (s *Set[T]) ForEach(walker func(T)) {
   237  	if s != nil {
   238  		map_.ForEachKey(s.elements, walker)
   239  	}
   240  }
   241  
   242  // Filter returns a stream consisting of elements that satisfy the condition of the 'predicate' function
   243  func (s *Set[T]) Filter(predicate func(T) bool) stream.Iter[T] {
   244  	h := s.Head()
   245  	return stream.New(loop.Filter(h.Next, predicate).Next)
   246  }
   247  
   248  // Filt returns a breakable stream consisting of elements that satisfy the condition of the 'predicate' function
   249  func (s Set[T]) Filt(predicate func(T) (bool, error)) breakStream.Iter[T] {
   250  	h := s.Head()
   251  	return breakStream.New(breakLoop.Filt(breakLoop.From(h.Next), predicate).Next)
   252  }
   253  
   254  // Convert returns a stream that applies the 'converter' function to the collection elements
   255  func (s *Set[T]) Convert(converter func(T) T) stream.Iter[T] {
   256  	return collection.Convert(s, converter)
   257  }
   258  
   259  // Conv returns a breakable stream that applies the 'converter' function to the collection elements
   260  func (s *Set[T]) Conv(converter func(T) (T, error)) breakStream.Iter[T] {
   261  	return collection.Conv(s, converter)
   262  }
   263  
   264  // Reduce reduces the elements into an one using the 'merge' function
   265  func (s *Set[T]) Reduce(merge func(T, T) T) (t T) {
   266  	if s != nil {
   267  		t, _ = map_.Reduce(s.elements, func(t1, t2 T, _, _ struct{}) (t T, out struct{}) {
   268  			return merge(t1, t2), out
   269  		})
   270  	}
   271  	return t
   272  }
   273  
   274  // HasAny finds the first element that satisfies the 'predicate' function condition and returns true if successful
   275  func (s *Set[K]) HasAny(predicate func(K) bool) bool {
   276  	if s != nil {
   277  		return map_.HasAny(s.elements, func(k K, _ struct{}) bool {
   278  			return predicate(k)
   279  		})
   280  	}
   281  	return false
   282  }
   283  
   284  // Sort transforms to the ordered Set contains sorted elements
   285  func (s *Set[T]) Sort(less slice.Less[T]) *ordered.Set[T] {
   286  	return s.sortBy(sort.Slice, less)
   287  }
   288  
   289  // StableSort transforms to the ordered Set contains sorted elements
   290  func (s *Set[T]) StableSort(less slice.Less[T]) *ordered.Set[T] {
   291  	return s.sortBy(sort.SliceStable, less)
   292  }
   293  
   294  func (s *Set[T]) sortBy(sorter slice.Sorter, less slice.Less[T]) *ordered.Set[T] {
   295  	var sortedElements []T
   296  	if s != nil {
   297  		sortedElements = slice.Clone(s.Slice())
   298  		slice.Sort(sortedElements, sorter, less)
   299  	}
   300  	return ordered.NewSet(sortedElements...)
   301  }
   302  
   303  func (s *Set[T]) String() string {
   304  	return slice.ToString(s.Slice())
   305  }