github.com/m4gshm/gollections@v0.0.10/collection/mutable/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  	iter "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 and an order slice as the internal storage.
    19  func WrapSet[T comparable](elements []T, uniques map[T]int) *Set[T] {
    20  	return &Set[T]{order: &elements, elements: uniques}
    21  }
    22  
    23  // Set is a collection implementation that provides element uniqueness and access order. Elements must be comparable.
    24  type Set[T comparable] struct {
    25  	order    *[]T
    26  	elements map[T]int
    27  }
    28  
    29  var (
    30  	_ c.Addable[int]                      = (*Set[int])(nil)
    31  	_ c.AddableNew[int]                   = (*Set[int])(nil)
    32  	_ c.AddableAll[c.ForEachLoop[int]]    = (*Set[int])(nil)
    33  	_ c.AddableAllNew[c.ForEachLoop[int]] = (*Set[int])(nil)
    34  	_ c.Deleteable[int]                   = (*Set[int])(nil)
    35  	_ c.DeleteableVerify[int]             = (*Set[int])(nil)
    36  	_ collection.Set[int]                 = (*Set[int])(nil)
    37  	_ loop.Looper[int, *SetIter[int]]     = (*Set[int])(nil)
    38  	_ fmt.Stringer                        = (*Set[int])(nil)
    39  )
    40  
    41  // Iter creates an iterator and returns as interface
    42  func (s *Set[T]) Iter() c.Iterator[T] {
    43  	h := s.Head()
    44  	return &h
    45  }
    46  
    47  // Loop creates an iterator and returns as implementation type reference
    48  func (s *Set[T]) Loop() *SetIter[T] {
    49  	h := s.Head()
    50  	return &h
    51  }
    52  
    53  // IterEdit creates iterator that can delete iterable elements
    54  func (s *Set[T]) IterEdit() c.DelIterator[T] {
    55  	h := s.Head()
    56  	return &h
    57  }
    58  
    59  // Head creates an iterator and returns as implementation type value
    60  func (s *Set[T]) Head() SetIter[T] {
    61  	var elements *[]T
    62  	if s != nil {
    63  		elements = s.order
    64  	}
    65  	return NewSetIter(elements, s.DeleteOne)
    66  }
    67  
    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.ForEachLoop[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.ForEachLoop[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(pos, *order)
   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 'walker' function for the elements. Return the c.ErrBreak to stop.
   236  func (s *Set[T]) For(walker 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, walker)
   245  }
   246  
   247  // ForEach applies the 'walker' function for every element
   248  func (s *Set[T]) ForEach(walker func(T)) {
   249  	if s != nil {
   250  		if order := s.order; order != nil {
   251  			slice.ForEach(*order, walker)
   252  		}
   253  	}
   254  }
   255  
   256  // Filter returns a stream consisting of elements that satisfy the condition of the 'predicate' function
   257  func (s *Set[T]) Filter(predicate func(T) bool) stream.Iter[T] {
   258  	h := s.Head()
   259  	return stream.New(iter.Filter(h.Next, predicate).Next)
   260  }
   261  
   262  // Filt returns a breakable stream consisting of elements that satisfy the condition of the 'predicate' function
   263  func (s *Set[T]) Filt(predicate func(T) (bool, error)) breakStream.Iter[T] {
   264  	h := s.Head()
   265  	return breakStream.New(breakLoop.Filt(breakLoop.From(h.Next), predicate).Next)
   266  }
   267  
   268  // Convert returns a stream that applies the 'converter' function to the collection elements
   269  func (s *Set[T]) Convert(converter func(T) T) stream.Iter[T] {
   270  	return collection.Convert(s, converter)
   271  }
   272  
   273  // Conv returns a breakable stream that applies the 'converter' function to the collection elements
   274  func (s *Set[T]) Conv(converter func(T) (T, error)) breakStream.Iter[T] {
   275  	return collection.Conv(s, converter)
   276  }
   277  
   278  // Reduce reduces the elements into an one using the 'merge' function
   279  func (s *Set[T]) Reduce(merge func(T, T) T) (t T) {
   280  	if s != nil {
   281  		if order := s.order; order != nil {
   282  			t = slice.Reduce(*order, merge)
   283  		}
   284  	}
   285  	return t
   286  }
   287  
   288  // HasAny finds the first element that satisfies the 'predicate' function condition and returns true if successful
   289  func (s *Set[K]) HasAny(predicate func(K) bool) bool {
   290  	if s != nil {
   291  		if order := s.order; order != nil {
   292  			return slice.HasAny(*order, predicate)
   293  		}
   294  	}
   295  	return false
   296  }
   297  
   298  // Sort sorts the elements
   299  func (s *Set[T]) Sort(less slice.Less[T]) *Set[T] {
   300  	return s.sortBy(sort.Slice, less)
   301  }
   302  
   303  // StableSort sorts the elements
   304  func (s *Set[T]) StableSort(less slice.Less[T]) *Set[T] {
   305  	return s.sortBy(sort.SliceStable, less)
   306  }
   307  
   308  func (s *Set[T]) sortBy(sorter slice.Sorter, less slice.Less[T]) *Set[T] {
   309  	if s != nil {
   310  		if order := s.order; order != nil {
   311  			slice.Sort(*order, sorter, less)
   312  		}
   313  	}
   314  	return s
   315  }
   316  
   317  func (s *Set[T]) String() string {
   318  	var elements []T
   319  	if s != nil {
   320  		if order := s.order; order != nil {
   321  			elements = *order
   322  		}
   323  	}
   324  	return slice.ToString(elements)
   325  }
   326  
   327  func addToSet[T comparable](e T, uniques map[T]int, order []T, pos int) ([]T, int) {
   328  	if _, ok := uniques[e]; !ok {
   329  		order = append(order, e)
   330  		uniques[e] = pos
   331  		pos++
   332  	}
   333  	return order, pos
   334  }