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  }