github.com/m4gshm/gollections@v0.0.10/kv/stream/stream.go (about) 1 package stream 2 3 import ( 4 breakKvLoop "github.com/m4gshm/gollections/break/kv/loop" 5 "github.com/m4gshm/gollections/break/kv/stream" 6 breakMapConvert "github.com/m4gshm/gollections/break/map_/convert" 7 breakFilter "github.com/m4gshm/gollections/break/map_/filter" 8 "github.com/m4gshm/gollections/kv" 9 kvloop "github.com/m4gshm/gollections/kv/loop" 10 "github.com/m4gshm/gollections/loop" 11 "github.com/m4gshm/gollections/map_/convert" 12 "github.com/m4gshm/gollections/map_/filter" 13 ) 14 15 // New instantiates StreamIter 16 func New[K comparable, V any, M map[K]V | map[K][]V](next func() (K, V, bool), collector MapCollector[K, V, M]) Iter[K, V, M] { 17 return Iter[K, V, M]{next: next, collector: collector} 18 } 19 20 // Iter is the key/value Iterator based stream implementation. 21 type Iter[K comparable, V any, M map[K]V | map[K][]V] struct { 22 next func() (K, V, bool) 23 collector MapCollector[K, V, M] 24 } 25 26 var ( 27 _ kv.Iterator[string, any] = (*Iter[string, any, map[string]any])(nil) 28 _ Stream[string, any, map[string]any] = (*Iter[string, any, map[string]any])(nil) 29 _ Stream[string, any, map[string][]any] = (*Iter[string, any, map[string][]any])(nil) 30 _ kvloop.Looper[string, any, Iter[string, any, map[string]any]] = (*Iter[string, any, map[string]any])(nil) 31 _ kvloop.Looper[string, any, Iter[string, any, map[string][]any]] = (*Iter[string, any, map[string][]any])(nil) 32 33 _ kv.Iterator[string, any] = Iter[string, any, map[string]any]{} 34 _ Stream[string, any, map[string]any] = Iter[string, any, map[string]any]{} 35 _ Stream[string, any, map[string][]any] = Iter[string, any, map[string][]any]{} 36 _ kvloop.Looper[string, any, Iter[string, any, map[string]any]] = Iter[string, any, map[string]any]{} 37 _ kvloop.Looper[string, any, Iter[string, any, map[string][]any]] = Iter[string, any, map[string][]any]{} 38 _ kv.IterFor[string, any, Iter[string, any, map[string][]any]] = Iter[string, any, map[string][]any]{} 39 ) 40 41 // Next implements kv.KVIterator 42 func (i Iter[K, V, M]) Next() (K, V, bool) { 43 return i.next() 44 } 45 46 // FilterKey returns a stream consisting of key/value pairs where the key satisfies the condition of the 'predicate' function 47 func (i Iter[K, V, M]) FilterKey(predicate func(K) bool) Iter[K, V, M] { 48 return New(kvloop.Filter(i.next, filter.Key[V](predicate)).Next, i.collector) 49 } 50 51 // FiltKey returns a stream consisting of key/value pairs where the key satisfies the condition of the 'predicate' function 52 func (i Iter[K, V, M]) FiltKey(predicate func(K) (bool, error)) stream.Iter[K, V, M] { 53 return stream.New(breakKvLoop.Filt(breakKvLoop.From(i.next), breakFilter.Key[V](predicate)).Next, collect(i.collector)) 54 } 55 56 // ConvertKey returns a stream that applies the 'converter' function to keys of the map 57 func (i Iter[K, V, M]) ConvertKey(by func(K) K) Iter[K, V, M] { 58 return New(kvloop.Convert(i.next, convert.Key[V](by)).Next, i.collector) 59 } 60 61 // ConvKey returns a stream that applies the 'converter' function to keys of the map 62 func (i Iter[K, V, M]) ConvKey(by func(K) (K, error)) stream.Iter[K, V, M] { 63 return stream.New(breakKvLoop.Conv(breakKvLoop.From(i.next), breakMapConvert.Key[V](by)).Next, collect(i.collector)) 64 } 65 66 // FilterValue returns a stream consisting of key/value pairs where the value satisfies the condition of the 'predicate' function 67 func (i Iter[K, V, M]) FilterValue(predicate func(V) bool) Iter[K, V, M] { 68 return New(kvloop.Filter(i.next, filter.Value[K](predicate)).Next, i.collector) 69 } 70 71 // FiltValue returns a stream consisting of key/value pairs where the value satisfies the condition of the 'predicate' function 72 func (i Iter[K, V, M]) FiltValue(predicate func(V) (bool, error)) stream.Iter[K, V, M] { 73 return stream.New(breakKvLoop.Filt(breakKvLoop.From(i.next), breakFilter.Value[K](predicate)).Next, collect(i.collector)) 74 } 75 76 // ConvertValue returns a stream that applies the 'converter' function to values of the map 77 func (i Iter[K, V, M]) ConvertValue(converter func(V) V) Iter[K, V, M] { 78 return New(kvloop.Convert(i.next, convert.Value[K](converter)).Next, i.collector) 79 } 80 81 // ConvValue returns a stream that applies the 'converter' function to values of the map 82 func (i Iter[K, V, M]) ConvValue(converter func(V) (V, error)) stream.Iter[K, V, M] { 83 return stream.New(breakKvLoop.Conv(breakKvLoop.From(i.next), breakMapConvert.Value[K](converter)).Next, collect(i.collector)) 84 } 85 86 // Filter returns a stream consisting of elements that satisfy the condition of the 'predicate' function 87 func (i Iter[K, V, M]) Filter(predicate func(K, V) bool) Iter[K, V, M] { 88 return New(kvloop.Filter(i.next, predicate).Next, i.collector) 89 } 90 91 // Filt returns a breakable stream consisting of elements that satisfy the condition of the 'predicate' function 92 func (i Iter[K, V, M]) Filt(predicate func(K, V) (bool, error)) stream.Iter[K, V, M] { 93 return stream.New(breakKvLoop.Filt(breakKvLoop.From(i.next), predicate).Next, collect(i.collector)) 94 } 95 96 // Convert returns a stream that applies the 'converter' function to the collection elements 97 func (i Iter[K, V, M]) Convert(converter func(K, V) (K, V)) Iter[K, V, M] { 98 return New(kvloop.Convert(i.next, converter).Next, i.collector) 99 } 100 101 // Conv returns a breakable stream that applies the 'converter' function to the collection elements 102 func (i Iter[K, V, M]) Conv(converter func(K, V) (K, V, error)) stream.Iter[K, V, M] { 103 return stream.New(breakKvLoop.Conv(breakKvLoop.From(i.next), converter).Next, collect(i.collector)) 104 } 105 106 // Track applies the 'tracker' function for key/value pairs. Return the c.ErrBreak to stop. 107 func (i Iter[K, V, M]) Track(tracker func(K, V) error) error { 108 return loop.Track(i.next, tracker) 109 } 110 111 // TrackEach applies the 'tracker' function for every key/value pairs 112 func (i Iter[K, V, M]) TrackEach(tracker func(K, V)) { 113 loop.TrackEach(i.next, tracker) 114 } 115 116 // Reduce reduces the key/value pairs into an one pair using the 'merge' function 117 func (i Iter[K, V, M]) Reduce(by func(K, K, V, V) (K, V)) (K, V) { 118 return kvloop.Reduce(i.next, by) 119 } 120 121 // HasAny finds the first key/value pari that satisfies the 'predicate' function condition and returns true if successful 122 func (i Iter[K, V, M]) HasAny(predicate func(K, V) bool) bool { 123 next := i.next 124 return kvloop.HasAny(next, predicate) 125 } 126 127 // Iter creates an iterator and returns as interface 128 func (i Iter[K, V, M]) Iter() kv.Iterator[K, V] { 129 return i 130 } 131 132 // Loop creates an iterator and returns as implementation type reference 133 func (i Iter[K, V, M]) Loop() Iter[K, V, M] { 134 return i 135 } 136 137 // Map collects the key/value pairs to a map 138 func (i Iter[K, V, M]) Map() M { 139 return i.collector(i.next) 140 } 141 142 // Start is used with for loop construct like 'for i, k, v, ok := i.Start(); ok; k, v, ok = i.Next() { }' 143 func (i Iter[K, V, M]) Start() (Iter[K, V, M], K, V, bool) { 144 k, v, ok := i.Next() 145 return i, k, v, ok 146 } 147 148 // MapCollector is Converter of key/value Iterator that collects all values to any slice or map, mostly used to extract slice fields to flatting a result 149 type MapCollector[K comparable, V any, M map[K]V | map[K][]V] func(next func() (K, V, bool)) M 150 151 func collect[K comparable, V any, M map[K]V | map[K][]V](collector MapCollector[K, V, M]) stream.MapCollector[K, V, M] { 152 return func(next func() (K, V, bool, error)) (M, error) { 153 var loopErr error 154 breakKvLoop.To(next, func(err error) { loopErr = err }) 155 return collector(breakKvLoop.To(next, func(err error) { loopErr = err })), loopErr 156 } 157 }