Documentation ¶
Overview ¶
Package itertools provides Iterator type to iteratively access elements of collections/sequences and many functions and methods to works with iterators.
Example (MapFilter) ¶
package main import ( "fmt" "github.com/KSpaceer/itertools" "strings" "time" ) // imitating account name or something type Account string // stub representation of financial transaction type Transaction struct { From Account To Account Amount int Timestamp time.Time } // stub representation of transaction message from message queue type Message struct { FromTo string Amount int Time string } func messageToTransaction(msg Message) Transaction { var tx Transaction parts := strings.SplitN(msg.FromTo, "---", 2) tx.From, tx.To = Account(parts[0]), Account(parts[1]) tx.Amount = msg.Amount tx.Timestamp, _ = time.Parse(time.RFC3339Nano, msg.Time) return tx } // mock fraud checker for financial transactions type FraudChecker struct { definitelyFraudulent Account } func (fc *FraudChecker) IsFraudulentTransaction(tx Transaction) bool { return tx.To == fc.definitelyFraudulent || tx.From == fc.definitelyFraudulent } // mock fraud transaction alerter type Alerter struct{} func (Alerter) Alert(tx Transaction) { var sb strings.Builder sb.WriteString("!!!FOUND FRAUD TRANSACTION!!!\n") sb.WriteString(fmt.Sprintf("From: %q\n", tx.From)) sb.WriteString(fmt.Sprintf("To: %q\n", tx.To)) sb.WriteString(fmt.Sprintf("Amount: %d\n", tx.Amount)) fmt.Println(sb.String()) } // mock consumer of message queue/broker type MessageConsumer []Message // imitating process of message consumption func (mc *MessageConsumer) StartConsume() <-chan Message { messages := make([]Message, len(*mc)) copy(messages, *mc) ch := make(chan Message) go func() { for _, msg := range messages { ch <- msg } close(ch) }() return ch } func main() { const fraud = "1" consumer := MessageConsumer{ { FromTo: "2---3", Amount: 15, Time: time.Now().Format(time.RFC3339Nano), }, { FromTo: "3---1", Amount: 15, Time: time.Now().Format(time.RFC3339Nano), }, { FromTo: "5---6", Amount: 13, Time: time.Now().Format(time.RFC3339Nano), }, { FromTo: "7---8", Amount: 5, Time: time.Now().Format(time.RFC3339Nano), }, { FromTo: "4---1", Amount: 10, Time: time.Now().Format(time.RFC3339Nano), }, { FromTo: "1---0", Amount: 25, Time: time.Now().Format(time.RFC3339Nano), }, } ch := consumer.StartConsume() fraudChecker := FraudChecker{definitelyFraudulent: fraud} alerter := Alerter{} iter := itertools.Map( // iterating over messages itertools.NewChanIterator(ch), // mapping them to transactions messageToTransaction, // keeping only fraudulent ones ).Filter(fraudChecker.IsFraudulentTransaction) iter.Range(func(tx Transaction) bool { alerter.Alert(tx) return true }) }
Output: !!!FOUND FRAUD TRANSACTION!!! From: "3" To: "1" Amount: 15 !!!FOUND FRAUD TRANSACTION!!! From: "4" To: "1" Amount: 10 !!!FOUND FRAUD TRANSACTION!!! From: "1" To: "0" Amount: 25
Example (MapReduce) ¶
package main import ( "fmt" "github.com/KSpaceer/itertools" "math" ) func main() { data := []int{6, 10, 7, 12, 6, 14, 8, 13, 10, 14} sum := itertools.Sum(itertools.NewSliceIterator(data)) avg := float64(sum) / float64(len(data)) stddev := itertools. Map( // iterating over data itertools.NewSliceIterator(data), // transforming data from int to float64 func(n int) float64 { return float64(n) }, ). // calculating standard deviation of data Reduce(0, func(acc float64, elem float64) float64 { return acc + (elem-avg)*(elem-avg) }) stddev = math.Sqrt(stddev / float64(len(data)-1)) fmt.Println("data:", data) fmt.Printf("standard deviation: %.2f", stddev) }
Output: data: [6 10 7 12 6 14 8 13 10 14] standard deviation: 3.16
Example (Set) ¶
package main import ( "fmt" "github.com/KSpaceer/itertools" "sync" "time" ) func main() { values := map[int]struct{}{} for i := 0; i < 1_000_000; i++ { values[i%40000] = struct{}{} } const batchSize = 2500 iter := itertools. // batching incoming values into batches with size batchSize (2500) Batched(itertools.NewMapKeysIterator(values). // keeping only numbers divisible by 4 Filter(func(n int) bool { return n%4 == 0 }), batchSize) var wg sync.WaitGroup for iter.Next() { batch := iter.Elem() wg.Add(1) go func() { defer wg.Done() process(batch) }() } wg.Wait() } func process(values []int) { // long processing imitation time.Sleep(time.Duration(len(values)) * time.Microsecond) fmt.Printf("processed %d items\n", len(values)) }
Output: processed 2500 items processed 2500 items processed 2500 items processed 2500 items
Index ¶
- func Find[T any](i *Iterator[T], f func(T) bool) (T, bool)
- func Max[T cmp.Ordered](i *Iterator[T]) T
- func Min[T cmp.Ordered](i *Iterator[T]) T
- func Sum[T Summable](i *Iterator[T]) T
- type AllocationOption
- type Enumeration
- type Iterator
- func Batched[T any](i *Iterator[T], batchSize int) *Iterator[[]T]
- func Chain[T any](iters ...*Iterator[T]) *Iterator[T]
- func Cycle[T any](i *Iterator[T], opts ...AllocationOption) *Iterator[T]
- func Enumerate[T any](i *Iterator[T]) *Iterator[Enumeration[T]]
- func Map[T, U any](i *Iterator[T], mapper func(T) U) *Iterator[U]
- func New[T any](f func() (T, bool)) *Iterator[T]
- func NewAsciiIterator(s string) *Iterator[byte]
- func NewChanIterator[T any](ch <-chan T) *Iterator[T]
- func NewMapIterator[K comparable, V any](m map[K]V) *Iterator[Pair[K, V]]
- func NewMapKeysIterator[K comparable, V any](m map[K]V) *Iterator[K]
- func NewMapValuesIterator[K comparable, V any](m map[K]V) *Iterator[V]
- func NewSliceIterator[S ~[]T, T any](s S) *Iterator[T]
- func NewUTF8Iterator(s string) *Iterator[rune]
- func Repeat[T any](elem T) *Iterator[T]
- func Zip[T, U any](t *Iterator[T], u *Iterator[U]) *Iterator[Pair[T, U]]
- func (i *Iterator[T]) All(f func(T) bool) bool
- func (i *Iterator[T]) Any(f func(T) bool) bool
- func (i *Iterator[T]) Collect(opts ...AllocationOption) []T
- func (i *Iterator[T]) Count() int
- func (i *Iterator[T]) Drop(n int) int
- func (i *Iterator[T]) Elem() T
- func (i *Iterator[T]) Filter(f func(T) bool) *Iterator[T]
- func (i *Iterator[T]) Limit(size int) *Iterator[T]
- func (i *Iterator[T]) Max(f func(T, T) int) T
- func (i *Iterator[T]) Next() bool
- func (i *Iterator[T]) Range(f func(T) bool)
- func (i *Iterator[T]) Reduce(acc T, f func(acc T, elem T) T) T
- func (i *Iterator[T]) WithStep(step int) *Iterator[T]
- type Pair
- type Summable
Examples ¶
- Package (MapFilter)
- Package (MapReduce)
- Package (Set)
- Batched
- Chain
- Cycle
- Enumerate
- Find (Found)
- Find (Not_found)
- Iterator.All (False)
- Iterator.All (True)
- Iterator.Any (False)
- Iterator.Any (True)
- Iterator.Collect
- Iterator.Count
- Iterator.Drop
- Iterator.Filter
- Iterator.Limit
- Iterator.Max
- Iterator.Range
- Iterator.Range (Conditional_stop)
- Iterator.Reduce
- Iterator.WithStep
- Map
- Max
- Min
- New
- NewAsciiIterator
- NewChanIterator
- NewMapIterator
- NewSliceIterator
- NewUTF8Iterator
- Repeat
- Zip
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Find ¶
Find applies function f to elements of iterator, returning first element for which the function returned true. The returned boolean value shows if the element was found (i.e. is valid). If no element was found, Find returns false as second returned value.
Example (Found) ¶
package main import ( "fmt" "github.com/KSpaceer/itertools" ) func main() { type Person struct { Name string Age uint } people := []Person{ {"Bob", 31}, {"John", 42}, {"Michael", 17}, {"Jenny", 26}, } target := "Michael" iter := itertools.NewSliceIterator(people) person, found := itertools.Find(iter, func(person Person) bool { return person.Name == target }) if found { fmt.Printf("Found person with name %q. Age: %d\n", person.Name, person.Age) } else { fmt.Printf("Failed to find person with name %q\n", target) } }
Output: Found person with name "Michael". Age: 17
Example (Not_found) ¶
package main import ( "fmt" "github.com/KSpaceer/itertools" ) func main() { type Person struct { Name string Age uint } people := []Person{ {"Bob", 31}, {"John", 42}, {"Michael", 17}, {"Jenny", 26}, } target := "Mike" iter := itertools.NewSliceIterator(people) person, found := itertools.Find(iter, func(person Person) bool { return person.Name == target }) if found { fmt.Printf("Found person with name %q. Age: %d\n", person.Name, person.Age) } else { fmt.Printf("Failed to find person with name %q\n", target) } }
Output: Failed to find person with name "Mike"
func Max ¶
Max return max value of iterator.
Example ¶
package main import ( "fmt" "github.com/KSpaceer/itertools" ) func main() { s := []int{-80, 23, 0, 54, 13, -39, 45, 33} iter := itertools.NewSliceIterator(s) fmt.Println("Max value:", itertools.Max(iter)) }
Output: Max value: 54
Types ¶
type AllocationOption ¶
type AllocationOption func(options *allocOptions)
AllocationOption allows to manipulate allocations in iteration methods/functions.
func WithPrealloc ¶
func WithPrealloc(prealloc int) AllocationOption
WithPrealloc sets preallocation size (capacity) for allocated buffers/slices.
type Enumeration ¶
Enumeration is a specific case of Pair for Enumerate function.
func (Enumeration[T]) Unpack ¶
func (p Enumeration[T]) Unpack() (T, int)
Unpack returns values of Enumeration as tuple.
type Iterator ¶
type Iterator[T any] struct { // contains filtered or unexported fields }
Iterator is used to process all elements of some collection or sequence. Iterator contains methods to access the elements and to process or aggregate them in many ways.
func Batched ¶
Batched creates new iterator that returns slices of T (aka batch) with size up to batchSize, using given source iterator.
Example ¶
package main import ( "fmt" "github.com/KSpaceer/itertools" ) func main() { s := []int{1, 2, 3, 4, 5, 6, 7, 8, 9} iter := itertools.Batched(itertools.NewSliceIterator(s), 2) for iter.Next() { fmt.Println("got batch:", iter.Elem()) } }
Output: got batch: [1 2] got batch: [3 4] got batch: [5 6] got batch: [7 8] got batch: [9]
func Chain ¶
Chain chains iterators, returning resulting chained iterator. The result iterator yields elements of the first iterator, then elements of the second one etc.
Example ¶
package main import ( "fmt" "github.com/KSpaceer/itertools" ) func main() { iter1 := itertools.NewSliceIterator([]byte("Hello")) ch := make(chan byte) go func() { ch <- ' ' close(ch) }() iter2 := itertools.NewChanIterator(ch) iter3 := itertools.NewAsciiIterator("World!") chainedIter := itertools.Chain(iter1, iter2, iter3) fmt.Println("chained collected result:", string(chainedIter.Collect())) }
Output: chained collected result: Hello World!
func Cycle ¶
func Cycle[T any](i *Iterator[T], opts ...AllocationOption) *Iterator[T]
Cycle creates new iterator that endlessly repeats elements of source iterator. If source iterator is empty, the cycle iterator is also empty.
Example ¶
package main import ( "fmt" "github.com/KSpaceer/itertools" ) func main() { s := []int{1, 2, 3} iter := itertools.Cycle(itertools.NewSliceIterator(s)) for i := 0; i < 10; i++ { iter.Next() fmt.Println(iter.Elem()) } }
Output: 1 2 3 1 2 3 1 2 3 1
func Enumerate ¶
func Enumerate[T any](i *Iterator[T]) *Iterator[Enumeration[T]]
Enumerate creates new iterator that returns Enumeration contating current element of source iterator along with current iteration count (starting from 0).
Example ¶
package main import ( "fmt" "github.com/KSpaceer/itertools" ) func main() { type Person struct { Name string Age uint } people := []Person{ {"Bob", 31}, {"John", 42}, {"Michael", 17}, {"Jenny", 26}, } iter := itertools.Enumerate(itertools.NewSliceIterator(people)) for iter.Next() { person, i := iter.Elem().Unpack() fmt.Printf("Index: %d ||| Name: %s ||| Age: %d\n", i, person.Name, person.Age) } }
Output: Index: 0 ||| Name: Bob ||| Age: 31 Index: 1 ||| Name: John ||| Age: 42 Index: 2 ||| Name: Michael ||| Age: 17 Index: 3 ||| Name: Jenny ||| Age: 26
func Map ¶
Map returns new iterator that yields elements of type U by calling mapper to each element of type T of source iterator.
Example ¶
package main import ( "fmt" "github.com/KSpaceer/itertools" "math" ) func main() { const maxPoints = 150 results := []int{25, 100, 95, 36, 145, 67, 49, 123} percentageIter := itertools.Map( itertools.NewSliceIterator(results), func(result int) int { return int(math.Round(float64(result) / maxPoints * 100)) }, ) fmt.Println("Results percentage:", percentageIter.Collect()) }
Output: Results percentage: [17 67 63 24 97 45 33 82]
func New ¶
New creates new Iterator using given iteration function. Function returns an element of collection and boolean value indicating if the element is valid (i.e. false means that the iteration is over).
Example ¶
package main import ( "fmt" "github.com/KSpaceer/itertools" ) func main() { arr := [5]int{5, 10, 15, 20, 25} var idx int // function to manually iterator over slice. // It is more comfortable to use itertools.NewSliceIterator in this case f := func() (int, bool) { if idx >= len(arr) { return 0, false } elem := arr[idx] idx++ return elem, true } iter := itertools.New(f) fmt.Println(iter.Next(), iter.Elem()) fmt.Println(iter.Next(), iter.Elem()) fmt.Println(iter.Next(), iter.Elem()) fmt.Println(iter.Next(), iter.Elem()) fmt.Println(iter.Next(), iter.Elem()) fmt.Println(iter.Next()) }
Output: true 5 true 10 true 15 true 20 true 25 false
func NewAsciiIterator ¶
NewAsciiIterator creates iterator yielding bytes from string (interpreting string as []byte).
Example ¶
package main import ( "fmt" "github.com/KSpaceer/itertools" "unicode" ) func main() { s := "Hello, World!" iter := itertools.NewAsciiIterator(s) iter = iter.Filter(func(b byte) bool { return unicode.IsPunct(rune(b)) }) fmt.Println("phrase punctuation signs:", string(iter.Collect())) }
Output: phrase punctuation signs: ,!
func NewChanIterator ¶
NewChanIterator creates iterator yielding values from channel until the channel is closed.
Example ¶
package main import ( "fmt" "github.com/KSpaceer/itertools" "slices" "sync" ) func main() { ch := make(chan int) var wg sync.WaitGroup for i := 0; i < 3; i++ { wg.Add(1) go func() { defer wg.Done() for j := 0; j < 5; j++ { ch <- j } }() } go func() { wg.Wait() close(ch) }() iter := itertools.NewChanIterator(ch) result := iter.Collect() slices.Sort(result) fmt.Println(result) }
Output: [0 0 0 1 1 1 2 2 2 3 3 3 4 4 4]
func NewMapIterator ¶
func NewMapIterator[K comparable, V any](m map[K]V) *Iterator[Pair[K, V]]
NewMapIterator creates iterator yielding key-value pairs from map. NewMapIterator uses reflect package to keep iteration state.
Example ¶
package main import ( "fmt" "github.com/KSpaceer/itertools" "slices" ) func main() { months := map[int]string{ 1: "January", 2: "February", 3: "March", 4: "April", 5: "May", 6: "June", 7: "July", 8: "August", 9: "September", 10: "October", 11: "November", 12: "December", } iter := itertools.NewMapIterator(months) summerMonths := []string{"June", "July", "August"} iter = iter.Filter(func(p itertools.Pair[int, string]) bool { return slices.Contains(summerMonths, p.Second) }) // iterating over map keys (months numbers) rather than entire key-value pairs numbersIter := itertools.Map(iter, func(p itertools.Pair[int, string]) int { return p.First }) summerMonthsNumbers := numbersIter.Collect() slices.Sort(summerMonthsNumbers) fmt.Println("summer months numbers:", summerMonthsNumbers) }
Output: summer months numbers: [6 7 8]
func NewMapKeysIterator ¶
func NewMapKeysIterator[K comparable, V any](m map[K]V) *Iterator[K]
NewMapKeysIterator creates iterator yielding keys from map. NewMapKeysIterator uses reflect package to keep iteration state.
func NewMapValuesIterator ¶
func NewMapValuesIterator[K comparable, V any](m map[K]V) *Iterator[V]
NewMapValuesIterator creates iterator yielding values from map. NewMapValuesIterator uses reflect package to keep iteration state.
func NewSliceIterator ¶
NewSliceIterator creates iterator for given slice, meaning iterator will yield all elements of the slice.
Example ¶
package main import ( "fmt" "github.com/KSpaceer/itertools" ) func main() { s := []int{1, 2, 3, 4, 5} iter := itertools.NewSliceIterator(s) for iter.Next() { fmt.Println(iter.Elem()) } fmt.Println("is finished:", !iter.Next()) }
Output: 1 2 3 4 5 is finished: true
func NewUTF8Iterator ¶
NewUTF8Iterator creates iterator yielding runes from string (interpreting string as []rune)
Example ¶
package main import ( "fmt" "github.com/KSpaceer/itertools" "unicode" ) func main() { s := "Hello, 世界" iter := itertools.NewUTF8Iterator(s) iter = iter.Filter(func(r rune) bool { return unicode.Is(unicode.Han, r) }) fmt.Println("chinese hieroglyphs:", string(iter.Collect())) }
Output: chinese hieroglyphs: 世界
func Repeat ¶
Repeat creates new iterator that endlessly yields elem.
Example ¶
package main import ( "fmt" "github.com/KSpaceer/itertools" ) func main() { iter := itertools.Repeat("HELLO") for i := 0; i < 5; i++ { iter.Next() fmt.Println(iter.Elem()) } }
Output: HELLO HELLO HELLO HELLO HELLO
func Zip ¶
Zip joins two iterators into a one yielding Pair of the iterators' elements. Returned iterator yields Pairs until one of source iterators is empty.
Example ¶
package main import ( "fmt" "github.com/KSpaceer/itertools" ) func main() { names := []string{"Bob", "John", "Michael", "Jenny"} ages := []uint{31, 42, 17, 26} nameIter := itertools.NewSliceIterator(names) ageIter := itertools.NewSliceIterator(ages) iter := itertools.Zip(nameIter, ageIter) for iter.Next() { name, age := iter.Elem().Unpack() fmt.Printf("Name: %s ::: Age: %d\n", name, age) } }
Output: Name: Bob ::: Age: 31 Name: John ::: Age: 42 Name: Michael ::: Age: 17 Name: Jenny ::: Age: 26
func (*Iterator[T]) All ¶
All applies function f to every element of iterator. If f returns true for all elements of iterator, All returns true. Otherwise, All returns false. All is lazy and will stop iterating after first element for which f returns false. All returns true for empty iterator.
Example (False) ¶
package main import ( "fmt" "github.com/KSpaceer/itertools" ) func main() { s := []int{-4, -3, -2, -1, 0, 1, 2, 3, 4} predicate := func(n int) bool { return n < 2 } iter := itertools.NewSliceIterator(s) fmt.Println(iter.All(predicate)) }
Output: false
Example (True) ¶
package main import ( "fmt" "github.com/KSpaceer/itertools" ) func main() { s := []int{-4, -3, -2, -1, 0, 1, 2, 3, 4} predicate := func(n int) bool { if n < 0 { n = -n } return n < 5 } iter := itertools.NewSliceIterator(s) fmt.Println(iter.All(predicate)) }
Output: true
func (*Iterator[T]) Any ¶
Any applies function f to every element of iterator. If f returns false for all elements of iterator, Any returns false. Otherwise, Any return true. Any is lazy and will stop iterating after first element for which f returns true. Any returns false for empty iterator.
Example (False) ¶
package main import ( "fmt" "github.com/KSpaceer/itertools" ) func main() { s := []int{-4, -3, -2, -1, 0, 1, 2, 3, 4} predicate := func(n int) bool { if n < 0 { n = -n } return n >= 5 } iter := itertools.NewSliceIterator(s) fmt.Println(iter.Any(predicate)) }
Output: false
Example (True) ¶
package main import ( "fmt" "github.com/KSpaceer/itertools" ) func main() { s := []int{-4, -3, -2, -1, 0, 1, 2, 3, 4} predicate := func(n int) bool { return n < 2 } iter := itertools.NewSliceIterator(s) fmt.Println(iter.Any(predicate)) }
Output: true
func (*Iterator[T]) Collect ¶
func (i *Iterator[T]) Collect(opts ...AllocationOption) []T
Collect returns all elements of iterator as slice.
Example ¶
package main import ( "fmt" "github.com/KSpaceer/itertools" ) func main() { s := []string{"First", "Second", "Third"} idx := len(s) - 1 // function to iterate over slice in reverse order f := func() (string, bool) { if idx < 0 { return "", false } elem := s[idx] idx-- return elem, true } iter := itertools.New(f) fmt.Println(iter.Collect()) }
Output: [Third Second First]
func (*Iterator[T]) Count ¶
Count returns amount of remaining elements in iterator. Call of Count consumes all elements.
Example ¶
package main import ( "fmt" "github.com/KSpaceer/itertools" ) func main() { s := []int{1, 2, 3, 4} iter := itertools.NewSliceIterator(s) fmt.Println(iter.Count()) }
Output: 4
func (*Iterator[T]) Drop ¶
Drop skips next n elements in iterator, returning amount of skipped elements (if iterator has fewer elements than n, returned value is equal to the amount of elements).
Example ¶
package main import ( "fmt" "github.com/KSpaceer/itertools" ) func main() { const skipNextTwo = 0x01 data := []byte{'H', 'e', 'l', 'l', 'o', 0x01, 'W', 'o', 'r', 'l', 'd'} iter := itertools.NewSliceIterator(data) for iter.Next() { elem := iter.Elem() if elem == skipNextTwo { dropped := iter.Drop(2) fmt.Printf("dropped %d elements\n", dropped) } else { fmt.Printf("%c\n", elem) } } }
Output: H e l l o dropped 2 elements r l d
func (*Iterator[T]) Elem ¶
func (i *Iterator[T]) Elem() T
Elem returns the current element of iterator. If iterator is empty (Next returns false), result is unspecified.
func (*Iterator[T]) Filter ¶
Filter produces new iterator that yields only elements for which function f returns true.
Example ¶
package main import ( "fmt" "github.com/KSpaceer/itertools" ) func main() { s := []int{1, 2, 3, 4, 5, 6, 7} oddFilter := func(n int) bool { return n%2 == 1 } evenFilter := func(n int) bool { return n%2 == 0 } oddIter := itertools.NewSliceIterator(s).Filter(oddFilter) evenIter := itertools.NewSliceIterator(s).Filter(evenFilter) fmt.Println(oddIter.Collect()) fmt.Println(evenIter.Collect()) }
Output: [1 3 5 7] [2 4 6]
func (*Iterator[T]) Limit ¶
Limit produces new iterator that can return at most size elements.
Example ¶
package main import ( "fmt" "github.com/KSpaceer/itertools" ) func main() { iter := itertools.NewAsciiIterator("Hello World!").Limit(5) for iter.Next() { fmt.Printf("%c\n", iter.Elem()) } }
Output: H e l l o
func (*Iterator[T]) Max ¶
Max returns max element of iterator, using provided comparison function. Comparison function returns next results:
- -1: if the first argument is less than second one
- 0: if two arguments are equal
- 1: if the first argument is greater than second one
Example ¶
package main import ( "cmp" "fmt" "github.com/KSpaceer/itertools" ) func main() { type Person struct { Name string Age uint } people := []Person{ {"Bob", 31}, {"John", 42}, {"Michael", 17}, {"Jenny", 26}, } iter := itertools.NewSliceIterator(people) oldest := iter.Max(func(a Person, b Person) int { return cmp.Compare(a.Age, b.Age) }) fmt.Printf("Oldest person: %s (age %d)\n", oldest.Name, oldest.Age) }
Output: Oldest person: John (age 42)
func (*Iterator[T]) Next ¶
Next proceeds iterator to the next element, returning boolean value to show that said element exists.
func (*Iterator[T]) Range ¶
Range calls function f for every element of iterator until the function returns false
Example ¶
package main import ( "fmt" "github.com/KSpaceer/itertools" ) func main() { s := []string{"First", "Second", "Third", "Fourth", "Fifth"} iter := itertools.NewSliceIterator(s) iter.Range(func(s string) bool { fmt.Println(s) return true }) }
Output: First Second Third Fourth Fifth
Example (Conditional_stop) ¶
package main import ( "fmt" "github.com/KSpaceer/itertools" ) func main() { s := []int{5, 4, 2, 0, -1, -8, -16} iter := itertools.NewSliceIterator(s) iter.Range(func(n int) bool { fmt.Println(n) if n < 0 { return false } return true }) }
Output: 5 4 2 0 -1
func (*Iterator[T]) Reduce ¶
func (i *Iterator[T]) Reduce(acc T, f func(acc T, elem T) T) T
Reduce applies given function f to every element of iterator, using previous accumulating state and returning updated accumulating state on each iteration. Reduce also accepts initial value for accumulating state. Reduce returns final accumulating state created after applying f to all elements of iterator.
Example ¶
package main import ( "fmt" "github.com/KSpaceer/itertools" ) func main() { s := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} sum := func(acc int, n int) int { return acc + n } iter := itertools.NewSliceIterator(s) fmt.Println("Sum of slice:", iter.Reduce(0, sum)) }
Output: Sum of slice: 55
func (*Iterator[T]) WithStep ¶
WithStep produces new iterator that yields every "step"th element of underlying iterator If step is non-positive, returns empty iterator.
Example ¶
package main import ( "fmt" "github.com/KSpaceer/itertools" ) func main() { s := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} iter := itertools.NewSliceIterator(s).WithStep(2) for iter.Next() { fmt.Println(iter.Elem()) } }
Output: 1 3 5 7 9
type Pair ¶
type Pair[T, U any] struct { First T Second U }
Pair is 2-size tuple of heterogeneous values.
type Summable ¶
type Summable interface { constraints.Integer | constraints.Float | constraints.Complex | ~string }