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

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