github.com/m4gshm/gollections@v0.0.10/kv/loop/api.go (about) 1 // Package loop provides helpers for loop operation over key/value pairs and iterator implementations 2 package loop 3 4 import ( 5 "github.com/m4gshm/gollections/break/kv/loop" 6 "github.com/m4gshm/gollections/map_/resolv" 7 ) 8 9 // Looper provides an iterable loop function 10 type Looper[K, V any, I interface{ Next() (K, V, bool) }] interface { 11 Loop() I 12 } 13 14 // Group collects sets of values grouped by keys obtained by passing a key/value iterator 15 func Group[K comparable, V any](next func() (K, V, bool)) map[K][]V { 16 return ToMapResolv(next, resolv.Append[K, V]) 17 } 18 19 // Reduce reduces the key/value pairs retrieved by the 'next' function into an one pair using the 'merge' function 20 func Reduce[K, V any](next func() (K, V, bool), merge func(K, K, V, V) (K, V)) (rk K, rv V) { 21 if k, v, ok := next(); ok { 22 rk, rv = k, v 23 } else { 24 return rk, rv 25 } 26 for k, v, ok := next(); ok; k, v, ok = next() { 27 rk, rv = merge(rk, k, rv, v) 28 } 29 return rk, rv 30 } 31 32 // Reducee reduces the key/value pairs retrieved by the 'next' function into an one pair using the 'merge' function 33 func Reducee[K, V any](next func() (K, V, bool), merge func(K, K, V, V) (K, V, error)) (rk K, rv V, err error) { 34 k, v, ok := next() 35 if !ok { 36 return rk, rv, nil 37 } 38 rk, rv = k, v 39 for { 40 if k, v, ok := next(); !ok { 41 return rk, rv, nil 42 } else if rk, rv, err = merge(rk, k, rv, v); err != nil { 43 return rk, rv, err 44 } 45 } 46 } 47 48 // HasAny finds the first key/value pair that satisfies the 'predicate' function condition and returns true if successful 49 func HasAny[K, V any](next func() (K, V, bool), predicate func(K, V) bool) bool { 50 _, _, ok := First(next, predicate) 51 return ok 52 } 53 54 // HasAnyy finds the first key/value pair that satisfies the 'predicate' function condition and returns true if successful 55 func HasAnyy[K, V any](next func() (K, V, bool), predicate func(K, V) (bool, error)) (bool, error) { 56 _, _, ok, err := Firstt(next, predicate) 57 return ok, err 58 } 59 60 // First returns the first key/value pair that satisfies the condition of the 'predicate' function 61 func First[K, V any](next func() (K, V, bool), predicate func(K, V) bool) (K, V, bool) { 62 for { 63 if k, v, ok := next(); !ok { 64 return k, v, false 65 } else if ok := predicate(k, v); ok { 66 return k, v, true 67 } 68 } 69 } 70 71 // Firstt returns the first key/value pair that satisfies the condition of the 'predicate' function 72 func Firstt[K, V any](next func() (K, V, bool), predicate func(K, V) (bool, error)) (K, V, bool, error) { 73 for { 74 if k, v, ok := next(); !ok { 75 return k, v, false, nil 76 } else if ok, err := predicate(k, v); err != nil || ok { 77 return k, v, ok, err 78 } 79 } 80 } 81 82 // Convert creates an iterator that applies a transformer to iterable key\values. 83 func Convert[K, V any, k2, v2 any](next func() (K, V, bool), converter func(K, V) (k2, v2)) ConvertIter[K, V, k2, v2, func(K, V) (k2, v2)] { 84 return ConvertIter[K, V, k2, v2, func(K, V) (k2, v2)]{next: next, converter: converter} 85 } 86 87 // Conv creates an iterator that applies a transformer to iterable key\values. 88 func Conv[K, V any, KOUT, VOUT any](next func() (K, V, bool), converter func(K, V) (KOUT, VOUT, error)) loop.ConvertIter[K, V, KOUT, VOUT] { 89 return loop.Conv(loop.From(next), converter) 90 } 91 92 // Filter creates an iterator that checks elements by a filter and returns successful ones 93 func Filter[K, V any](next func() (K, V, bool), filter func(K, V) bool) FilterIter[K, V] { 94 return FilterIter[K, V]{next: next, filter: filter} 95 } 96 97 // Filt creates an iterator that checks elements by a filter and returns successful ones 98 func Filt[K, V any](next func() (K, V, bool), filter func(K, V) (bool, error)) loop.FiltIter[K, V] { 99 return loop.Filt(loop.From(next), filter) 100 } 101 102 // ToMapResolv collects key\value elements to a map by iterating over the elements with resolving of duplicated key values 103 func ToMapResolv[K comparable, V, VR any](next func() (K, V, bool), resolver func(bool, K, VR, V) VR) map[K]VR { 104 m := map[K]VR{} 105 for k, v, ok := next(); ok; k, v, ok = next() { 106 exists, ok := m[k] 107 m[k] = resolver(ok, k, exists, v) 108 } 109 return m 110 } 111 112 // ToMap collects key\value elements to a map by iterating over the elements 113 func ToMap[K comparable, V any](next func() (K, V, bool)) map[K]V { 114 return ToMapResolv(next, resolv.First[K, V]) 115 } 116 117 // ToSlice collects key\value elements to a slice by iterating over the elements 118 func ToSlice[K, V, T any](next func() (K, V, bool), converter func(K, V) T) []T { 119 s := []T{} 120 for key, val, ok := next(); ok; key, val, ok = next() { 121 s = append(s, converter(key, val)) 122 } 123 return s 124 }