github.com/m4gshm/gollections@v0.0.10/loop/key_valuer.go (about) 1 package loop 2 3 import "github.com/m4gshm/gollections/kv" 4 5 // NewKeyValuer creates instance of the KeyValuer 6 func NewKeyValuer[T any, K, V any](next func() (T, bool), keyExtractor func(T) K, valsExtractor func(T) V) KeyValuer[T, K, V] { 7 return KeyValuer[T, K, V]{next: next, keyExtractor: keyExtractor, valExtractor: valsExtractor} 8 } 9 10 // NewMultipleKeyValuer creates instance of the MultipleKeyValuer 11 func NewMultipleKeyValuer[T any, K, V any](next func() (T, bool), keysExtractor func(T) []K, valsExtractor func(T) []V) *MultipleKeyValuer[T, K, V] { 12 return &MultipleKeyValuer[T, K, V]{next: next, keysExtractor: keysExtractor, valsExtractor: valsExtractor} 13 } 14 15 // KeyValuer is the Iterator wrapper that converts an element to a key\value pair and iterates over these pairs 16 type KeyValuer[T, K, V any] struct { 17 next func() (T, bool) 18 keyExtractor func(T) K 19 valExtractor func(T) V 20 } 21 22 var _ kv.Iterator[int, string] = (*KeyValuer[any, int, string])(nil) 23 var _ kv.Iterator[int, string] = KeyValuer[any, int, string]{} 24 var _ kv.IterFor[int, string, KeyValuer[any, int, string]] = KeyValuer[any, int, string]{} 25 26 // Track takes key, value pairs retrieved by the iterator. Can be interrupt by returning ErrBreak 27 func (kv KeyValuer[T, K, V]) Track(traker func(key K, value V) error) error { 28 return Track(kv.Next, traker) 29 } 30 31 // TrackEach takes all key, value pairs retrieved by the iterator 32 func (kv KeyValuer[T, K, V]) TrackEach(traker func(key K, value V)) { 33 TrackEach(kv.Next, traker) 34 } 35 36 // Next returns the next element. 37 // The ok result indicates whether the element was returned by the iterator. 38 // If ok == false, then the iteration must be completed. 39 func (kv KeyValuer[T, K, V]) Next() (key K, value V, ok bool) { 40 if next := kv.next; next != nil { 41 if elem, nextOk := next(); nextOk { 42 key = kv.keyExtractor(elem) 43 value = kv.valExtractor(elem) 44 ok = true 45 } 46 } 47 return key, value, ok 48 } 49 50 // Start is used with for loop construct like 'for i, k, v, ok := i.Start(); ok; k, v, ok = i.Next() { }' 51 func (kv KeyValuer[T, K, V]) Start() (KeyValuer[T, K, V], K, V, bool) { 52 return startKvIt[K, V](kv) 53 } 54 55 // MultipleKeyValuer is the Iterator wrapper that converts an element to a key\value pair and iterates over these pairs 56 type MultipleKeyValuer[T, K, V any] struct { 57 next func() (T, bool) 58 keysExtractor func(T) []K 59 valsExtractor func(T) []V 60 keys []K 61 values []V 62 ki, vi int 63 } 64 65 var _ kv.Iterator[int, string] = (*MultipleKeyValuer[any, int, string])(nil) 66 var _ kv.IterFor[int, string, *MultipleKeyValuer[any, int, string]] = (*MultipleKeyValuer[any, int, string])(nil) 67 68 // Track takes key, value pairs retrieved by the iterator. Can be interrupt by returning ErrBreak 69 func (kv *MultipleKeyValuer[T, K, V]) Track(traker func(key K, value V) error) error { 70 return Track(kv.Next, traker) 71 } 72 73 // TrackEach takes all key, value pairs retrieved by the iterator 74 func (kv *MultipleKeyValuer[T, K, V]) TrackEach(traker func(key K, value V)) { 75 TrackEach(kv.Next, traker) 76 } 77 78 // Next returns the next element. 79 // The ok result indicates whether the element was returned by the iterator. 80 // If ok == false, then the iteration must be completed. 81 func (kv *MultipleKeyValuer[T, K, V]) Next() (key K, value V, ok bool) { 82 if kv != nil { 83 if next := kv.next; next != nil { 84 for !ok { 85 var ( 86 keys, values = kv.keys, kv.values 87 keysLen, valuesLen = len(keys), len(values) 88 lastKeyIndex, lastValIndex = keysLen - 1, valuesLen - 1 89 ) 90 91 if keysLen > 0 && kv.ki >= 0 && kv.ki <= lastKeyIndex { 92 key = keys[kv.ki] 93 ok = true 94 } 95 if valuesLen > 0 && kv.vi >= 0 && kv.vi <= lastValIndex { 96 value = values[kv.vi] 97 ok = true 98 } 99 100 if kv.ki < lastKeyIndex { 101 kv.ki++ 102 } else if kv.vi < lastValIndex { 103 kv.ki = 0 104 kv.vi++ 105 } else if elem, nextOk := next(); nextOk { 106 kv.keys = kv.keysExtractor(elem) 107 kv.values = kv.valsExtractor(elem) 108 kv.ki, kv.vi = 0, 0 109 } else { 110 kv.keys, kv.values = nil, nil 111 break 112 } 113 } 114 } 115 } 116 return key, value, ok 117 } 118 119 // Start is used with for loop construct like 'for i, k, v, ok := i.Start(); ok; k, v, ok = i.Next() { }' 120 func (kv *MultipleKeyValuer[T, K, V]) Start() (*MultipleKeyValuer[T, K, V], K, V, bool) { 121 return startKvIt[K, V](kv) 122 }