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

     1  package ordered
     2  
     3  import (
     4  	"fmt"
     5  
     6  	breakLoop "github.com/m4gshm/gollections/break/kv/loop"
     7  	breakMapFilter "github.com/m4gshm/gollections/break/kv/predicate"
     8  	breakMapConvert "github.com/m4gshm/gollections/break/map_/convert"
     9  	"github.com/m4gshm/gollections/c"
    10  	"github.com/m4gshm/gollections/collection"
    11  	"github.com/m4gshm/gollections/kv/convert"
    12  	kvloop "github.com/m4gshm/gollections/kv/loop"
    13  	filter "github.com/m4gshm/gollections/kv/predicate"
    14  	"github.com/m4gshm/gollections/map_"
    15  	"github.com/m4gshm/gollections/slice"
    16  )
    17  
    18  // WrapMap instantiates ordered Map using a map and an order slice as internal storage.
    19  func WrapMap[K comparable, V any](order []K, elements map[K]V) Map[K, V] {
    20  	return Map[K, V]{order: order, elements: elements}
    21  }
    22  
    23  // Map is a collection implementation that provides elements access by an unique key.
    24  type Map[K comparable, V any] struct {
    25  	order    []K
    26  	elements map[K]V
    27  }
    28  
    29  var (
    30  	_ collection.Map[int, any]                    = (*Map[int, any])(nil)
    31  	_ collection.Map[int, any]                    = Map[int, any]{}
    32  	_ c.KeyVal[MapKeys[int], MapValues[int, any]] = (*Map[int, any])(nil)
    33  	_ c.KeyVal[MapKeys[int], MapValues[int, any]] = Map[int, any]{}
    34  	_ fmt.Stringer                                = (*Map[int, any])(nil)
    35  	_ fmt.Stringer                                = Map[int, any]{}
    36  )
    37  
    38  // All is used to iterate through the collection using `for ... range`. Supported since go 1.22 with GOEXPERIMENT=rangefunc enabled.
    39  func (m Map[K, V]) All(consumer func(K, V) bool) {
    40  	map_.TrackOrderedWhile(m.order, m.elements, consumer)
    41  }
    42  
    43  // Loop creates a loop to iterate through the collection.
    44  func (m Map[K, V]) Loop() kvloop.Loop[K, V] {
    45  	h := m.Head()
    46  	return h.Next
    47  }
    48  
    49  // Deprecated: Head is deprecated. Will be replaced by rance-over function iterator.
    50  // Head creates an iterator to iterate through the collection.
    51  func (m Map[K, V]) Head() MapIter[K, V] {
    52  	return NewMapIter(m.elements, slice.NewHead(m.order))
    53  }
    54  
    55  // Deprecated: First is deprecated. Will be replaced by rance-over function iterator.
    56  // First returns the first key/value pair of the map, an iterator to iterate over the remaining pair, and true\false marker of availability next pairs.
    57  // If no more then ok==false.
    58  func (m Map[K, V]) First() (MapIter[K, V], K, V, bool) {
    59  	var (
    60  		iterator           = m.Head()
    61  		firstK, firstV, ok = iterator.Next()
    62  	)
    63  	return iterator, firstK, firstV, ok
    64  }
    65  
    66  // Deprecated: Tail is deprecated. Will be replaced by rance-over function iterator.
    67  // Tail creates an iterator pointing to the end of the map
    68  func (m Map[K, V]) Tail() MapIter[K, V] {
    69  	return NewMapIter(m.elements, slice.NewTail(m.order))
    70  }
    71  
    72  // Map collects the key/value pairs to a map
    73  func (m Map[K, V]) Map() map[K]V {
    74  	return map_.Clone(m.elements)
    75  }
    76  
    77  // Len returns amount of elements
    78  func (m Map[K, V]) Len() int {
    79  	return len(m.order)
    80  }
    81  
    82  // IsEmpty returns true if the map is empty
    83  func (m Map[K, V]) IsEmpty() bool {
    84  	return m.Len() == 0
    85  }
    86  
    87  // Contains checks is the map contains a key
    88  func (m Map[K, V]) Contains(key K) (ok bool) {
    89  	if m.elements != nil {
    90  		_, ok = m.elements[key]
    91  	}
    92  	return ok
    93  }
    94  
    95  // Get returns the value for a key.
    96  // If ok==false, then the map does not contain the key.
    97  func (m Map[K, V]) Get(key K) (element V, ok bool) {
    98  	if m.elements != nil {
    99  		element, ok = m.elements[key]
   100  	}
   101  	return element, ok
   102  }
   103  
   104  // Keys resutrns keys collection
   105  func (m Map[K, V]) Keys() MapKeys[K] {
   106  	return WrapKeys(m.order)
   107  }
   108  
   109  // Values resutrns values collection
   110  func (m Map[K, V]) Values() MapValues[K, V] {
   111  	return WrapVal(m.order, m.elements)
   112  }
   113  
   114  // Sort returns sorted by keys map
   115  func (m Map[K, V]) Sort(comparer slice.Comparer[K]) Map[K, V] {
   116  	return m.sortBy(slice.Sort, comparer)
   117  }
   118  
   119  // StableSort returns sorted by keys map
   120  func (m Map[K, V]) StableSort(comparer slice.Comparer[K]) Map[K, V] {
   121  	return m.sortBy(slice.StableSort, comparer)
   122  }
   123  
   124  func (m Map[K, V]) sortBy(sorter func([]K, slice.Comparer[K]) []K, comparer slice.Comparer[K]) Map[K, V] {
   125  	return WrapMap(sorter(slice.Clone(m.order), comparer), m.elements)
   126  }
   127  
   128  func (m Map[K, V]) String() string {
   129  	return map_.ToStringOrdered(m.order, m.elements)
   130  }
   131  
   132  // Track applies the 'consumer' function for all key/value pairs until the consumer returns the c.Break to stop.
   133  func (m Map[K, V]) Track(consumer func(K, V) error) error {
   134  	return map_.TrackOrdered(m.order, m.elements, consumer)
   135  }
   136  
   137  // TrackEach applies the 'consumer' function for every key/value pairs
   138  func (m Map[K, V]) TrackEach(consumer func(K, V)) {
   139  	map_.TrackEachOrdered(m.order, m.elements, consumer)
   140  }
   141  
   142  // FilterKey returns a loop consisting of key/value pairs where the key satisfies the condition of the 'predicate' function
   143  func (m Map[K, V]) FilterKey(predicate func(K) bool) kvloop.Loop[K, V] {
   144  	h := m.Head()
   145  	return kvloop.Filter(h.Next, filter.Key[V](predicate))
   146  }
   147  
   148  // FiltKey returns a loop consisting of key/value pairs where the key satisfies the condition of the 'predicate' function
   149  func (m Map[K, V]) FiltKey(predicate func(K) (bool, error)) breakLoop.Loop[K, V] {
   150  	h := m.Head()
   151  	return kvloop.Filt(h.Next, breakMapFilter.Key[V](predicate))
   152  }
   153  
   154  // ConvertKey returns a loop that applies the 'converter' function to keys of the map
   155  func (m Map[K, V]) ConvertKey(by func(K) K) kvloop.Loop[K, V] {
   156  	h := m.Head()
   157  	return kvloop.Convert(h.Next, convert.Key[V](by))
   158  }
   159  
   160  // ConvKey returns a loop that applies the 'converter' function to keys of the map
   161  func (m Map[K, V]) ConvKey(converter func(K) (K, error)) breakLoop.Loop[K, V] {
   162  	h := m.Head()
   163  	return kvloop.Conv(h.Next, breakMapConvert.Key[V](converter))
   164  }
   165  
   166  // FilterValue returns a loop consisting of key/value pairs where the value satisfies the condition of the 'predicate' function
   167  func (m Map[K, V]) FilterValue(predicate func(V) bool) kvloop.Loop[K, V] {
   168  	h := m.Head()
   169  	return kvloop.Filter(h.Next, filter.Value[K](predicate))
   170  }
   171  
   172  // FiltValue returns a breakable loop consisting of key/value pairs where the value satisfies the condition of the 'predicate' function
   173  func (m Map[K, V]) FiltValue(predicate func(V) (bool, error)) breakLoop.Loop[K, V] {
   174  	h := m.Head()
   175  	return kvloop.Filt(h.Next, breakMapFilter.Value[K](predicate))
   176  }
   177  
   178  // ConvertValue returns a loop that applies the 'converter' function to values of the map
   179  func (m Map[K, V]) ConvertValue(converter func(V) V) kvloop.Loop[K, V] {
   180  	h := m.Head()
   181  	return kvloop.Convert(h.Next, convert.Value[K](converter))
   182  }
   183  
   184  // ConvValue returns a breakable loop that applies the 'converter' function to values of the map
   185  func (m Map[K, V]) ConvValue(converter func(V) (V, error)) breakLoop.Loop[K, V] {
   186  	h := m.Head()
   187  	return kvloop.Conv(h.Next, breakMapConvert.Value[K](converter))
   188  }
   189  
   190  // Filter returns a loop consisting of elements that satisfy the condition of the 'predicate' function
   191  func (m Map[K, V]) Filter(predicate func(K, V) bool) kvloop.Loop[K, V] {
   192  	h := m.Head()
   193  	return kvloop.Filter(h.Next, predicate)
   194  }
   195  
   196  // Filt returns a breakable loop consisting of elements that satisfy the condition of the 'predicate' function
   197  func (m Map[K, V]) Filt(predicate func(K, V) (bool, error)) breakLoop.Loop[K, V] {
   198  	h := m.Head()
   199  	return kvloop.Filt(h.Next, predicate)
   200  }
   201  
   202  // Convert returns a loop that applies the 'converter' function to the collection elements
   203  func (m Map[K, V]) Convert(converter func(K, V) (K, V)) kvloop.Loop[K, V] {
   204  	h := m.Head()
   205  	return kvloop.Convert(h.Next, converter)
   206  }
   207  
   208  // Conv returns a breakable loop that applies the 'converter' function to the collection elements
   209  func (m Map[K, V]) Conv(converter func(K, V) (K, V, error)) breakLoop.Loop[K, V] {
   210  	h := m.Head()
   211  	return kvloop.Conv(h.Next, converter)
   212  }
   213  
   214  // Reduce reduces the key/value pairs of the map into an one pair using the 'merge' function
   215  func (m Map[K, V]) Reduce(merge func(K, K, V, V) (K, V)) (K, V) {
   216  	return map_.Reduce(m.elements, merge)
   217  }
   218  
   219  // HasAny finds the first key/value pair that satisfies the 'predicate' function condition and returns true if successful
   220  func (m Map[K, V]) HasAny(predicate func(K, V) bool) bool {
   221  	return map_.HasAny(m.elements, predicate)
   222  }
   223  
   224  func addToMap[K comparable, V any](key K, val V, order []K, uniques map[K]V) []K {
   225  	if _, ok := uniques[key]; !ok {
   226  		order = append(order, key)
   227  		uniques[key] = val
   228  	}
   229  	return order
   230  }