Documentation
¶
Overview ¶
Package itu provides iterator utilities for Go.
It offers small, composable building blocks for working with iter.Seq types, focusing on lazy, streaming-friendly iteration and functional-style composition.
Index ¶
- func All[T any](seq iter.Seq[T], pred func(T) bool) bool
- func All2[K, V any](seq iter.Seq2[K, V], pred func(K, V) bool) bool
- func Any[T any](seq iter.Seq[T], pred func(T) bool) bool
- func Any2[K, V any](seq iter.Seq2[K, V], pred func(K, V) bool) bool
- func Chain[T any](seqs ...iter.Seq[T]) iter.Seq[T]
- func Chain2[K, V any](seqs ...iter.Seq2[K, V]) iter.Seq2[K, V]
- func Compare[E cmp.Ordered](seq1 iter.Seq[E], seq2 iter.Seq[E]) int
- func CompareFunc[E1, E2 any](seq1 iter.Seq[E1], seq2 iter.Seq[E2], cmpFn func(E1, E2) int) int
- func CompareFunc2[K1, V1, K2, V2 any](seq1 iter.Seq2[K1, V1], seq2 iter.Seq2[K2, V2], cmpFn func(K1, V1, K2, V2) int) int
- func Count[T any](seq iter.Seq[T]) int
- func Count2[K, V any](seq iter.Seq2[K, V]) int
- func Cycle[T any](seq iter.Seq[T]) iter.Seq[T]
- func Cycle2[A, B any](seq iter.Seq2[A, B]) iter.Seq2[A, B]
- func Empty[T any]() iter.Seq[T]
- func Empty2[A, B any]() iter.Seq2[A, B]
- func Enumerate[T any](seq iter.Seq[T]) iter.Seq2[int, T]
- func Equal[T comparable](seq1, seq2 iter.Seq[T]) bool
- func Equal2[K, V comparable](seq1 iter.Seq2[K, V], seq2 iter.Seq2[K, V]) bool
- func EqualFunc[E1, E2 any](seq1 iter.Seq[E1], seq2 iter.Seq[E2], eqFn func(E1, E2) bool) bool
- func EqualFunc2[K1, V1, K2, V2 any](seq1 iter.Seq2[K1, V1], seq2 iter.Seq2[K2, V2], eqFn func(K1, V1, K2, V2) bool) bool
- func Filter[T any](seq iter.Seq[T], pred func(T) bool) iter.Seq[T]
- func Filter2[K, V any](seq iter.Seq2[K, V], pred func(K, V) bool) iter.Seq2[K, V]
- func Find[T any](seq iter.Seq[T], pred func(T) bool) (value T, ok bool)
- func Find2[K, V any](seq iter.Seq2[K, V], pred func(K, V) bool) (k K, v V, ok bool)
- func Flatten[T any](seq iter.Seq[iter.Seq[T]]) iter.Seq[T]
- func FlattenTo2[K, V any](seq iter.Seq[iter.Seq2[K, V]]) iter.Seq2[K, V]
- func Fold[T, R any](seq iter.Seq[T], acc R, fn func(R, T) R) R
- func Fold2[K, V, R any](seq iter.Seq2[K, V], acc R, fn func(R, K, V) R) R
- func Intersperse[T any](seq iter.Seq[T], sep T) iter.Seq[T]
- func Last[T any](seq iter.Seq[T]) (value T, ok bool)
- func Last2[K, V any](seq iter.Seq2[K, V]) (k K, v V, ok bool)
- func Map[T, R any](seq iter.Seq[T], fn func(T) R) iter.Seq[R]
- func Map2[K, V, RK, RV any](seq iter.Seq2[K, V], fn func(K, V) (RK, RV)) iter.Seq2[RK, RV]
- func Map2To[TK, TV, R any](seq iter.Seq2[TK, TV], fn func(TK, TV) R) iter.Seq[R]
- func MapTo2[T, RK, RV any](seq iter.Seq[T], fn func(T) (RK, RV)) iter.Seq2[RK, RV]
- func Nth[T any](seq iter.Seq[T], n int) (value T, ok bool)
- func Nth2[K, V any](seq iter.Seq2[K, V], n int) (k K, v V, ok bool)
- func Of[T any](items ...T) iter.Seq[T]
- func Range[T Integer](start, end T) iter.Seq[T]
- func RangeBy[T Integer](start, end, step T) iter.Seq[T]
- func RangeFrom[T Integer](start T) iter.Seq[T]
- func RangeFromBy[T Integer](start, step T) iter.Seq[T]
- func RangeInclusive[T Integer](start, end T) iter.Seq[T]
- func RangeInclusiveBy[T Integer](start, end, step T) iter.Seq[T]
- func Reduce[T any](seq iter.Seq[T], fn func(T, T) T) (result T, ok bool)
- func ReduceOr[T any](seq iter.Seq[T], def T, fn func(T, T) T) T
- func Skip[T any](seq iter.Seq[T], n int) iter.Seq[T]
- func Skip2[K, V any](seq iter.Seq2[K, V], n int) iter.Seq2[K, V]
- func SkipWhile[T any](seq iter.Seq[T], pred func(T) bool) iter.Seq[T]
- func SkipWhile2[K, V any](seq iter.Seq2[K, V], pred func(K, V) bool) iter.Seq2[K, V]
- func StepBy[T any](seq iter.Seq[T], n int) iter.Seq[T]
- func StepBy2[K, V any](seq iter.Seq2[K, V], n int) iter.Seq2[K, V]
- func Take[T any](seq iter.Seq[T], n int) iter.Seq[T]
- func Take2[K, V any](seq iter.Seq2[K, V], n int) iter.Seq2[K, V]
- func TakeWhile[T any](seq iter.Seq[T], pred func(T) bool) iter.Seq[T]
- func TakeWhile2[K, V any](seq iter.Seq2[K, V], pred func(K, V) bool) iter.Seq2[K, V]
- func Zip[T1, T2 any](seq1 iter.Seq[T1], seq2 iter.Seq[T2]) iter.Seq2[T1, T2]
- type Integer
Examples ¶
- All
- All2
- Any
- Any2
- Chain
- Chain2
- Compare
- CompareFunc
- CompareFunc2
- Count
- Count2
- Cycle
- Cycle2
- Enumerate
- Equal
- Equal2
- EqualFunc
- EqualFunc2
- Filter
- Filter2
- Find
- Find2
- Flatten
- FlattenTo2
- Fold
- Fold2
- Intersperse
- Intersperse (Single)
- Last
- Last2
- Map
- Map2
- Map2To
- MapTo2
- Nth
- Nth2
- Of
- Range
- RangeBy
- RangeFrom
- RangeFromBy
- RangeInclusive
- RangeInclusiveBy
- Reduce
- Reduce (Empty)
- ReduceOr
- Skip
- Skip2
- SkipWhile
- SkipWhile2
- StepBy
- StepBy2
- Take
- Take2
- TakeWhile
- TakeWhile2
- Zip
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func All ¶ added in v0.7.1
All tests if every element of seq matches pred. All consumes seq eagerly and stops as soon as pred returns false. If seq is empty, All returns true.
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
seq := slices.Values([]int{2, 4, 6})
fmt.Println(itu.All(seq, func(v int) bool { return v%2 == 0 }))
}
Output: true
func All2 ¶ added in v0.7.1
All2 tests if every pair (k, v) of seq matches pred. All2 consumes seq eagerly and stops as soon as pred returns false. If seq is empty, All2 returns true.
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
// slices.All turns a slice into an iterator that yields index/value pairs.
seq := slices.All([]string{"a", "bb", "ccc"})
fmt.Println(itu.All2(seq, func(_ int, v string) bool { return len(v) >= 2 }))
}
Output: false
func Any ¶ added in v0.7.1
Any tests if at least one element of seq matches pred. Any consumes seq eagerly and stops as soon as pred returns true. If seq is empty, Any returns false.
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
seq := slices.Values([]int{1, 2, 3})
fmt.Println(itu.Any(seq, func(v int) bool { return v%2 == 0 }))
}
Output: true
func Any2 ¶ added in v0.7.1
Any2 tests if at least one pair (k, v) of seq matches pred. Any2 consumes seq eagerly and stops as soon as pred returns true. If seq is empty, Any2 returns false.
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
// slices.All turns a slice into an iterator that yields index/value pairs.
seq := slices.All([]string{"a", "bb", "ccc"})
fmt.Println(itu.Any2(seq, func(_ int, v string) bool { return len(v) >= 4 }))
}
Output: false
func Chain ¶ added in v0.3.1
Chain returns a lazy iterator that yields elements from each seq in seqs, in order. Values are produced only as the returned iterator is consumed.
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
first := slices.Values([]int{1, 2})
second := slices.Values([]int{})
third := slices.Values([]int{3, 4, 5})
chained := itu.Chain(first, second, third)
for v := range chained {
fmt.Println(v)
}
}
Output: 1 2 3 4 5
func Chain2 ¶ added in v0.3.1
Chain2 returns a lazy iterator that yields pairs from each seq in seqs, in order. Values are produced only as the returned iterator is consumed.
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
// slices.All returns an iter.Seq2 over index/value pairs.
first := slices.All([]string{"a", "b"})
second := slices.All([]string{})
third := slices.All([]string{"c"})
chained := itu.Chain2(first, second, third)
for i, v := range chained {
fmt.Printf("%d:%s\n", i, v)
}
}
Output: 0:a 1:b 0:c
func Compare ¶ added in v0.7.1
Compare compares the elements of seq1 and seq2, using cmp.Compare on each pair of elements. The elements are compared sequentially, starting at the first yielded value, until one element is not equal to the other.
The result of comparing the first non-matching elements is returned. If both sequences are equal until one of them ends, the shorter sequence is considered less than the longer one.
Compare consumes the input sequences eagerly as needed; it stops as soon as a mismatch is found or either sequence ends. If both sequences yield an identical infinite stream of values, Compare does not return.
The result is 0 if seq1 == seq2, -1 if seq1 < seq2, and +1 if seq1 > seq2.
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
fmt.Println(itu.Compare(slices.Values([]int{1, 2, 3}), slices.Values([]int{1, 2, 3})))
fmt.Println(itu.Compare(slices.Values([]int{1, 2}), slices.Values([]int{1, 2, 0})))
fmt.Println(itu.Compare(slices.Values([]int{1, 2, 5}), slices.Values([]int{1, 2, 4})))
}
Output: 0 -1 1
func CompareFunc ¶ added in v0.7.1
CompareFunc compares the elements of seq1 and seq2, using cmpFn to compare each pair of elements. The elements are compared sequentially, starting at the first yielded value, until cmpFn reports a mismatch.
The result is -1 if the first non-matching elements compare less than, +1 if they compare greater than, and 0 if all compared elements match and both sequences end at the same time. If both sequences are equal until one of them ends, the shorter sequence is considered less than the longer one.
CompareFunc consumes the input sequences eagerly as needed; it stops as soon as a mismatch is found or either sequence ends. If both sequences yield an identical infinite stream of values, CompareFunc does not return.
Example ¶
package main
import (
"cmp"
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
cmpLen := func(a int, b string) int { return cmp.Compare(a, len(b)) }
fmt.Println(itu.CompareFunc(
slices.Values([]int{1, 2, 3}),
slices.Values([]string{"a", "bb", "ccc"}),
cmpLen,
))
fmt.Println(itu.CompareFunc(
slices.Values([]int{1, 2, 4}),
slices.Values([]string{"a", "bb", "ccc"}),
cmpLen,
))
}
Output: 0 1
func CompareFunc2 ¶ added in v0.7.1
func CompareFunc2[K1, V1, K2, V2 any](seq1 iter.Seq2[K1, V1], seq2 iter.Seq2[K2, V2], cmpFn func(K1, V1, K2, V2) int) int
CompareFunc2 compares the pairs of seq1 and seq2, using cmpFn to compare each pair (k1, v1) and (k2, v2). The pairs are compared sequentially, starting at the first yielded pair, until cmpFn reports a mismatch.
The result is -1 if the first non-matching pairs compare less than, +1 if they compare greater than, and 0 if all compared pairs match and both sequences end at the same time. If both sequences are equal until one of them ends, the shorter sequence is considered less than the longer one.
CompareFunc2 consumes the input sequences eagerly as needed; it stops as soon as a mismatch is found or either sequence ends. If both sequences yield an identical infinite stream of pairs, CompareFunc2 does not return.
Example ¶
package main
import (
"cmp"
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
cmpPair := func(k1 int, v1 string, k2 int64, v2 int) int {
if c := cmp.Compare(int64(k1), k2); c != 0 {
return c
}
return cmp.Compare(len(v1), v2)
}
fmt.Println(itu.CompareFunc2(
itu.Zip(slices.Values([]int{1, 2, 3}), slices.Values([]string{"a", "bb", "ccc"})),
itu.Zip(slices.Values([]int64{1, 2, 3}), slices.Values([]int{1, 2, 3})),
cmpPair,
))
fmt.Println(itu.CompareFunc2(
itu.Zip(slices.Values([]int{1, 2, 4}), slices.Values([]string{"a", "bb", "ccc"})),
itu.Zip(slices.Values([]int64{1, 2, 3}), slices.Values([]int{1, 2, 3})),
cmpPair,
))
}
Output: 0 1
func Count ¶ added in v0.6.1
Count consumes seq eagerly and returns the number of yielded elements. If the result overflows, Count panics.
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
seq := slices.Values([]int{10, 20, 30, 40})
fmt.Println(itu.Count(seq))
}
Output: 4
func Count2 ¶ added in v0.6.1
Count2 consumes seq eagerly and returns the number of yielded pairs. If the result overflows, Count2 panics.
Example ¶
package main
import (
"fmt"
"maps"
"github.com/lymar/itu"
)
func main() {
// maps.All returns an iter.Seq2 over key/value pairs.
// Count the number of "facts" in the map.
m := map[string]int{
"Go": 2009,
"Rust": 2010,
"Elixir": 2011,
}
seq := maps.All(m)
fmt.Println(itu.Count2(seq))
}
Output: 3
func Cycle ¶ added in v0.7.1
Cycle returns a lazy iterator that repeats seq in a cycle.
Cycle consumes seq eagerly to build an internal slice copy of all values, then returns an iterator that yields those values repeatedly until the consumer stops.
If seq yields no values, Cycle returns an empty iterator.
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
input := slices.Values([]int{1, 2, 3})
cycle := itu.Cycle(input)
first8 := itu.Take(cycle, 8)
// Cycle is effectively infinite for non-empty inputs, so we take N values.
for v := range first8 {
fmt.Println(v)
}
}
Output: 1 2 3 1 2 3 1 2
func Cycle2 ¶ added in v0.7.1
Cycle2 returns a lazy iterator that repeats pairs (a, b) from seq in a cycle.
Cycle2 consumes seq eagerly to build an internal slice copy of all pairs, then returns an iterator that yields those pairs repeatedly until the consumer stops.
If seq yields no pairs, Cycle2 returns an empty iterator.
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
// slices.All returns an iter.Seq2 over index/value pairs.
input := slices.All([]string{"a", "b"})
cycle := itu.Cycle2(input)
first5 := itu.Take2(cycle, 5)
// Cycle2 is effectively infinite for non-empty inputs, so we take N pairs.
for i, v := range first5 {
fmt.Printf("%d %s\n", i, v)
}
}
Output: 0 a 1 b 0 a 1 b 0 a
func Enumerate ¶ added in v0.7.1
Enumerate returns a lazy iterator that yields pairs (i, x) for each element x in seq.
The index i starts at 0 and increments by 1 for each yielded element. Values are produced only as the returned iterator is consumed.
If advancing the index would overflow int, iteration stops (it does not wrap around).
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
seq := slices.Values([]string{"zero", "one", "two"})
for i, s := range itu.Enumerate(seq) {
fmt.Printf("%d:%s\n", i, s)
}
}
Output: 0:zero 1:one 2:two
func Equal ¶ added in v0.7.1
func Equal[T comparable](seq1, seq2 iter.Seq[T]) bool
Equal reports whether seq1 and seq2 yield the same values in the same order.
The sequences are compared sequentially, starting at the first yielded value. Equal consumes the input sequences eagerly as needed; it stops as soon as a mismatch is found or either sequence ends. If both sequences yield an identical infinite stream of values, Equal does not return.
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
fmt.Println(itu.Equal(slices.Values([]int{1, 2, 3}), slices.Values([]int{1, 2, 3})))
fmt.Println(itu.Equal(slices.Values([]int{1, 2}), slices.Values([]int{1, 2, 0})))
fmt.Println(itu.Equal(slices.Values([]int{1, 2, 3}), slices.Values([]int{1, 2, 4})))
}
Output: true false false
func Equal2 ¶ added in v0.7.1
Equal2 reports whether seq1 and seq2 yield the same pairs (k, v) in the same order.
The sequences are compared sequentially, starting at the first yielded pair. Equal2 consumes the input sequences eagerly as needed; it stops as soon as a mismatch is found or either sequence ends. If both sequences yield an identical infinite stream of pairs, Equal2 does not return.
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
seq1 := itu.Zip(slices.Values([]int{1, 2, 3}), slices.Values([]string{"a", "bb", "ccc"}))
seq2 := itu.Zip(slices.Values([]int{1, 2, 3}), slices.Values([]string{"a", "bb", "ccc"}))
fmt.Println(itu.Equal2(seq1, seq2))
seq3 := itu.Zip(slices.Values([]int{1, 2, 3}), slices.Values([]string{"a", "bb", "ccc"}))
seq4 := itu.Zip(slices.Values([]int{1, 2, 4}), slices.Values([]string{"a", "bb", "ccc"}))
fmt.Println(itu.Equal2(seq3, seq4))
}
Output: true false
func EqualFunc ¶ added in v0.7.1
EqualFunc reports whether seq1 and seq2 yield matching values in the same order, as determined by eqFn.
The sequences are compared sequentially, starting at the first yielded value. EqualFunc consumes the input sequences eagerly as needed; it stops as soon as eqFn reports a mismatch or either sequence ends. If both sequences yield an identical infinite stream of values and eqFn reports a match for every pair, EqualFunc does not return.
EqualFunc panics if eqFn is nil.
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
eqLen := func(a int, b string) bool { return a == len(b) }
fmt.Println(itu.EqualFunc(
slices.Values([]int{1, 2, 3}),
slices.Values([]string{"a", "bb", "ccc"}),
eqLen,
))
fmt.Println(itu.EqualFunc(
slices.Values([]int{1, 2, 4}),
slices.Values([]string{"a", "bb", "ccc"}),
eqLen,
))
}
Output: true false
func EqualFunc2 ¶ added in v0.7.1
func EqualFunc2[K1, V1, K2, V2 any](seq1 iter.Seq2[K1, V1], seq2 iter.Seq2[K2, V2], eqFn func(K1, V1, K2, V2) bool) bool
EqualFunc2 reports whether seq1 and seq2 yield matching pairs in the same order, as determined by eqFn.
The sequences are compared sequentially, starting at the first yielded pair. EqualFunc2 consumes the input sequences eagerly as needed; it stops as soon as eqFn reports a mismatch or either sequence ends. If both sequences yield an identical infinite stream of pairs and eqFn reports a match for every pair, EqualFunc2 does not return.
EqualFunc2 panics if eqFn is nil.
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
eqPair := func(k1 int, v1 string, k2 int64, v2 int) bool {
return int64(k1) == k2 && len(v1) == v2
}
seq1 := itu.Zip(slices.Values([]int{1, 2, 3}), slices.Values([]string{"a", "bb", "ccc"}))
seq2 := itu.Zip(slices.Values([]int64{1, 2, 3}), slices.Values([]int{1, 2, 3}))
fmt.Println(itu.EqualFunc2(seq1, seq2, eqPair))
seq3 := itu.Zip(slices.Values([]int{1, 2, 3}), slices.Values([]string{"a", "bb", "cccc"}))
seq4 := itu.Zip(slices.Values([]int64{1, 2, 3}), slices.Values([]int{1, 2, 3}))
fmt.Println(itu.EqualFunc2(seq3, seq4, eqPair))
}
Output: true false
func Filter ¶
Filter returns a lazy iterator over the elements of seq for which pred returns true. Elements are tested only as the returned iterator is consumed.
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
input := slices.Values([]int{0, 1, 2, 3, 4, 5})
evenNumbers := itu.Filter(input, func(v int) bool {
return v%2 == 0
})
for v := range evenNumbers {
fmt.Println(v)
}
}
Output: 0 2 4
func Filter2 ¶ added in v0.5.1
Filter2 returns a lazy iterator over the pairs of seq for which pred returns true. Pairs are tested only as the returned iterator is consumed.
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
// slices.All returns an iter.Seq2 over index/value pairs.
input := slices.All([]string{"aa", "bb", "ccc", "d"})
filtered := itu.Filter2(input, func(i int, s string) bool {
return i%2 == 0 && len(s) >= 2
})
for i, s := range filtered {
fmt.Printf("%d:%s\n", i, s)
}
}
Output: 0:aa 2:ccc
func Find ¶ added in v0.7.1
Find searches for an element of seq that satisfies pred. Find consumes seq eagerly and stops as soon as pred returns true. If no element matches, Find returns the zero value of T and ok=false.
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
v, ok := itu.Find(slices.Values([]int{1, 2, 3}), func(v int) bool { return v%2 == 0 })
fmt.Println(v, ok)
}
Output: 2 true
func Find2 ¶ added in v0.7.1
Find2 searches for a pair (k, v) of seq that satisfies pred. Find2 consumes seq eagerly and stops as soon as pred returns true. If no pair matches, Find2 returns zero values of K and V and ok=false.
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
// slices.All turns a slice into an iterator that yields index/value pairs.
k, v, ok := itu.Find2(slices.All([]string{"a", "bb", "ccc"}), func(_ int, v string) bool {
return len(v) >= 2
})
fmt.Println(k, v, ok)
}
Output: 1 bb true
func Flatten ¶ added in v0.7.1
Flatten returns a lazy iterator that yields elements from each inner sequence in seq, in order.
Values are produced only as the returned iterator is consumed.
Example ¶
package main
import (
"fmt"
"iter"
"slices"
"github.com/lymar/itu"
)
func main() {
inners := []iter.Seq[int]{
slices.Values([]int{1, 2}),
slices.Values([]int{}),
slices.Values([]int{3}),
}
outer := slices.Values(inners)
flat := itu.Flatten[int](outer)
for v := range flat {
fmt.Println(v)
}
}
Output: 1 2 3
func FlattenTo2 ¶ added in v0.7.1
FlattenTo2 returns a lazy iterator that yields pairs (k, v) from each inner sequence in seq, in order.
Values are produced only as the returned iterator is consumed.
Example ¶
package main
import (
"fmt"
"iter"
"slices"
"github.com/lymar/itu"
)
func main() {
// slices.All returns an iter.Seq2 over index/value pairs.
inners := []iter.Seq2[int, string]{
slices.All([]string{"a", "bb"}),
slices.All([]string{"x"}),
}
outer := slices.Values(inners)
flat := itu.FlattenTo2[int, string](outer)
for i, s := range flat {
fmt.Printf("%d:%s\n", i, s)
}
}
Output: 0:a 1:bb 0:x
func Fold ¶ added in v0.7.1
Fold folds seq from left to right, starting with acc. For each element x in seq it updates the accumulator as: acc = fn(acc, x). Fold consumes seq eagerly and returns the final accumulator. If seq is empty, Fold returns acc.
Note: if R is a reference type (map, slice, pointer, etc.), fn may mutate the accumulator value.
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
input := slices.Values([]int{1, 2, 3, 4, 5})
sum := itu.Fold(input, "", func(acc string, v int) string {
return acc + fmt.Sprintf("%d ", v)
})
fmt.Println(sum)
}
Output: 1 2 3 4 5
func Fold2 ¶ added in v0.7.1
Fold2 folds seq from left to right, starting with acc. For each pair (k, v) in seq it updates the accumulator as: acc = fn(acc, k, v). Fold2 consumes seq eagerly and returns the final accumulator. If seq is empty, Fold2 returns acc.
Note: if R is a reference type (map, slice, pointer, etc.), fn may mutate the accumulator value.
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
// slices.All returns an iter.Seq2 over index/value pairs.
input := slices.All([]string{"a", "bb", "ccc"})
result := itu.Fold2(input, "", func(acc string, i int, s string) string {
return acc + fmt.Sprintf("%d:%s ", i, s)
})
fmt.Println(result)
}
Output: 0:a 1:bb 2:ccc
func Intersperse ¶ added in v0.7.1
Intersperse returns a lazy iterator that yields the elements of seq with sep inserted between each pair of adjacent elements. Values are produced only as the returned iterator is consumed.
Example ¶
package main
import (
"fmt"
"slices"
"strings"
"github.com/lymar/itu"
)
func main() {
input := slices.Values([]string{"a", "b", "c"})
result := itu.Intersperse(input, "-")
var b strings.Builder
for s := range result {
b.WriteString(s)
}
fmt.Println(b.String())
}
Output: a-b-c
Example (Single) ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
input := slices.Values([]int{42})
result := itu.Intersperse(input, 0)
for v := range result {
fmt.Println(v)
}
}
Output: 42
func Last ¶ added in v0.8.1
Last returns the last element produced by seq.
Last consumes seq eagerly. If seq is empty, Last returns the zero value of T and ok=false.
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
v, ok := itu.Last(slices.Values([]int{10, 20, 30}))
fmt.Println(v, ok)
}
Output: 30 true
func Last2 ¶ added in v0.8.1
Last2 returns the last pair (k, v) produced by seq.
Last2 consumes seq eagerly. If seq is empty, Last2 returns the zero values of K and V and ok=false.
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
// slices.All turns a slice into an iterator that yields index/value pairs.
k, v, ok := itu.Last2(slices.All([]string{"a", "bb", "ccc"}))
fmt.Println(k, v, ok)
}
Output: 2 ccc true
func Map ¶
Map returns a lazy iterator that yields fn(x) for each element x in seq. Values are produced only as the returned iterator is consumed.
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
input := slices.Values([]int{0, 1, 2})
result := itu.Map(input, func(v int) string {
return fmt.Sprintf("[ %d ]", v+1)
})
for v := range result {
fmt.Println(v)
}
}
Output: [ 1 ] [ 2 ] [ 3 ]
func Map2 ¶ added in v0.4.1
Map2 returns a lazy iterator that yields pairs (rk, rv) produced by fn(k, v) for each input pair (k, v) from seq.
Values are produced only as the returned iterator is consumed.
Example ¶
package main
import (
"fmt"
"slices"
"strings"
"github.com/lymar/itu"
)
func main() {
// slices.All returns an iter.Seq2 over index/value pairs.
input := slices.All([]string{"a", "bb"})
result := itu.Map2(input, func(i int, s string) (string, int) {
return strings.ToUpper(s), i
})
for s, i := range result {
fmt.Printf("%s:%d\n", s, i)
}
}
Output: A:0 BB:1
func Map2To ¶ added in v0.4.1
Map2To returns a lazy iterator that yields fn(k, v) for each input pair (k, v) from seq.
Values are produced only as the returned iterator is consumed.
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
// slices.All returns an iter.Seq2 over index/value pairs.
input := slices.All([]string{"x", "y"})
result := itu.Map2To(input, func(i int, s string) string {
return fmt.Sprintf("%d=%s", i, s)
})
for v := range result {
fmt.Println(v)
}
}
Output: 0=x 1=y
func MapTo2 ¶ added in v0.4.1
MapTo2 returns a lazy iterator that yields pairs (rk, rv) produced by fn(x) for each element x in seq.
Values are produced only as the returned iterator is consumed.
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
input := slices.Values([]int{2, 3})
result := itu.MapTo2(input, func(v int) (string, int) {
return fmt.Sprintf("key=%d", v), v * v
})
for label, sq := range result {
fmt.Printf("%s:%d\n", label, sq)
}
}
Output: key=2:4 key=3:9
func Nth ¶ added in v0.8.1
Nth returns the element of seq at the zero-based index n.
Nth consumes seq eagerly and stops as soon as the n-th element is reached. If n is negative, or seq ends before producing the n-th element, Nth returns the zero value of T and ok=false.
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
v, ok := itu.Nth(slices.Values([]int{10, 20, 30}), 1)
fmt.Println(v, ok)
}
Output: 20 true
func Nth2 ¶ added in v0.8.1
Nth2 returns the pair (k, v) of seq at the zero-based index n.
Nth2 consumes seq eagerly and stops as soon as the n-th pair is reached. If n is negative, or seq ends before producing the n-th pair, Nth2 returns the zero values of K and V and ok=false.
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
// slices.All turns a slice into an iterator that yields index/value pairs.
k, v, ok := itu.Nth2(slices.All([]string{"a", "bb", "ccc"}), 2)
fmt.Println(k, v, ok)
}
Output: 2 ccc true
func Of ¶ added in v0.7.1
Of returns an iterator that yields each value from items in order.
If items is empty, Of yields no values.
Example ¶
package main
import (
"fmt"
"github.com/lymar/itu"
)
func main() {
seq := itu.Of("a", "b", "c")
for v := range seq {
fmt.Println(v)
}
}
Output: a b c
func Range ¶ added in v0.2.1
Range returns a lazy iterator that counts from start towards end with step 1.
It yields the half-open range [start, end): start, start+1, ..., end-1.
If start >= end, Range yields no values. If advancing the current value would overflow the underlying integer type, the sequence stops (it does not wrap around).
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
fmt.Println(slices.Collect(itu.Range(3, 7)))
}
Output: [3 4 5 6]
func RangeBy ¶ added in v0.2.1
RangeBy returns a lazy iterator that counts from start towards end using step.
For step > 0 it yields the half-open range [start, end) by repeatedly adding step while the current value is < end. For step < 0 it yields the half-open range (end, start] by repeatedly adding step while the current value is > end.
If step == 0, RangeBy treats it as non-negative: it yields no values when start >= end, and otherwise produces an infinite sequence of start values until the consumer stops.
If advancing the current value overflows the underlying integer type, the sequence stops (it does not wrap around).
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
fmt.Println(slices.Collect(itu.RangeBy(0, 5, 2)))
}
Output: [0 2 4]
func RangeFrom ¶ added in v0.2.1
RangeFrom returns a lazy iterator that starts at start and keeps advancing by 1 until the next step would overflow the underlying integer type (it does not wrap around).
Values are produced only as the returned iterator is consumed.
Example ¶
package main
import (
"fmt"
"github.com/lymar/itu"
)
func main() {
seq := itu.RangeFrom(-2)
out := make([]int, 0, 5)
for v := range seq {
out = append(out, v)
if len(out) == cap(out) {
break
}
}
fmt.Println(out)
}
Output: [-2 -1 0 1 2]
func RangeFromBy ¶ added in v0.2.1
RangeFromBy returns a lazy iterator that starts at start and keeps advancing by step until the next step would overflow the underlying integer type (it does not wrap around).
If step == 0, RangeFromBy produces an infinite sequence of start values until the consumer stops.
Example ¶
package main
import (
"fmt"
"github.com/lymar/itu"
)
func main() {
seq := itu.RangeFromBy(10, 3)
out := make([]int, 0, 5)
for v := range seq {
out = append(out, v)
if len(out) == cap(out) {
break
}
}
fmt.Println(out)
}
Output: [10 13 16 19 22]
func RangeInclusive ¶ added in v0.2.1
RangeInclusive returns a lazy iterator that counts from start towards end with step 1, including end.
It yields the closed range [start, end]: start, start+1, ..., end.
If start > end, RangeInclusive yields no values. If advancing the current value would overflow the underlying integer type, the sequence stops (it does not wrap around).
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
fmt.Println(slices.Collect(itu.RangeInclusive(3, 7)))
}
Output: [3 4 5 6 7]
func RangeInclusiveBy ¶ added in v0.2.1
RangeInclusiveBy returns a lazy iterator that counts from start towards end using step, including end.
For step > 0 it yields the closed range [start, end] by repeatedly adding step while the current value is <= end. For step < 0 it yields the closed range [end, start] in descending order by repeatedly adding step while the current value is >= end.
If step == 0, RangeInclusiveBy treats it as non-negative: it yields no values when start > end, and otherwise produces an infinite sequence of start values until the consumer stops.
If advancing the current value overflows the underlying integer type, the sequence stops (it does not wrap around).
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
fmt.Println(slices.Collect(itu.RangeInclusiveBy(0, 4, 2)))
}
Output: [0 2 4]
func Reduce ¶
Reduce reduces seq from left to right. It uses the first element of seq as the initial accumulator, then for each subsequent element x updates the accumulator as: acc = fn(acc, x). Reduce consumes seq eagerly.
If seq is empty, Reduce returns the zero value of T and ok=false.
Note: if T is a reference type (map, slice, pointer, etc.), fn may mutate the accumulator value.
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
input := slices.Values([]int{1, 2, 3, 4})
sum, ok := itu.Reduce(input, func(a, b int) int { return a + b })
fmt.Println(sum, ok)
}
Output: 10 true
Example (Empty) ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
sum, ok := itu.Reduce(slices.Values([]int(nil)), func(a, b int) int { return a + b })
fmt.Println(sum, ok)
}
Output: 0 false
func ReduceOr ¶ added in v0.7.1
ReduceOr reduces seq from left to right, like Reduce.
If seq is empty, ReduceOr returns def.
Note: if T is a reference type (map, slice, pointer, etc.), fn may mutate the accumulator value.
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
empty := slices.Values([]int(nil))
sum := itu.ReduceOr(empty, 123, func(a, b int) int { return a + b })
fmt.Println(sum)
}
Output: 123
func Skip ¶ added in v0.7.1
Skip returns a lazy iterator that skips the first n elements of seq.
It consumes and discards up to n values from seq, then yields the remaining values (if any). Values are produced only as the returned iterator is consumed.
Skip panics if n is negative.
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
seq := slices.Values([]int{10, 11, 12, 13, 14, 15})
fmt.Println(slices.Collect(itu.Skip(seq, 2)))
}
Output: [12 13 14 15]
func Skip2 ¶ added in v0.7.1
Skip2 returns a lazy iterator that skips the first n pairs from seq.
It consumes and discards up to n pairs from seq, then yields the remaining pairs (if any). Pairs are produced only as the returned iterator is consumed.
Skip2 panics if n is negative.
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
// slices.All returns an iter.Seq2 over index/value pairs.
all := slices.All([]string{"a", "b", "c", "d"})
seq := itu.Skip2(all, 2)
for i, v := range seq {
fmt.Printf("%d:%s\n", i, v)
}
}
Output: 2:c 3:d
func SkipWhile ¶ added in v0.7.1
SkipWhile returns a lazy iterator that skips elements from seq while pred returns true.
It consumes and discards consecutive values from seq while pred returns true. As soon as pred returns false for a value, that value and all remaining values are yielded.
Values are tested and produced only as the returned iterator is consumed.
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
seq := slices.Values([]int{10, 11, 12, 13, 14, 15})
out := slices.Collect(itu.SkipWhile(seq, func(v int) bool { return v < 12 }))
fmt.Println(out)
}
Output: [12 13 14 15]
func SkipWhile2 ¶ added in v0.7.1
SkipWhile2 returns a lazy iterator that skips pairs (k, v) from seq while pred returns true.
It consumes and discards consecutive pairs from seq while pred returns true. As soon as pred returns false for a pair, that pair and all remaining pairs are yielded.
Pairs are tested and produced only as the returned iterator is consumed.
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
// slices.All returns an iter.Seq2 over index/value pairs.
all := slices.All([]string{"a", "b", "stop", "c"})
seq := itu.SkipWhile2(all, func(_ int, v string) bool { return v != "stop" })
for i, v := range seq {
fmt.Printf("%d:%s\n", i, v)
}
}
Output: 2:stop 3:c
func StepBy ¶ added in v0.7.1
StepBy returns a lazy iterator that yields the first element from seq, then yields every n-th element after that.
For example, for seq producing [0 1 2 3 4 5] and n=2, StepBy yields [0 2 4]. Values are produced only as the returned iterator is consumed.
StepBy panics if n is not positive.
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
seq := slices.Values([]int{0, 1, 2, 3, 4, 5})
fmt.Println(slices.Collect(itu.StepBy(seq, 2)))
}
Output: [0 2 4]
func StepBy2 ¶ added in v0.7.1
StepBy2 returns a lazy iterator that yields the first pair (k, v) from seq, then yields every n-th pair after that.
Pairs are produced only as the returned iterator is consumed.
StepBy2 panics if n is not positive.
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
// slices.All returns an iter.Seq2 over index/value pairs.
all := slices.All([]string{"a", "b", "c", "d", "e", "f"})
seq := itu.StepBy2(all, 2)
for i, v := range seq {
fmt.Printf("%d:%s\n", i, v)
}
}
Output: 0:a 2:c 4:e
func Take ¶ added in v0.7.1
Take returns a lazy iterator that yields at most n elements from seq.
It yields the first n values from seq, or fewer if seq runs out of values. Values are produced only as the returned iterator is consumed.
Take panics if n is negative.
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
seq := slices.Values([]int{10, 11, 12, 13, 14, 15})
fmt.Println(slices.Collect(itu.Take(seq, 3)))
}
Output: [10 11 12]
func Take2 ¶ added in v0.7.1
Take2 returns a lazy iterator that yields at most n pairs from seq.
It yields the first n pairs from seq, or fewer if seq runs out of values. Pairs are produced only as the returned iterator is consumed.
Take2 panics if n is negative.
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
// slices.All returns an iter.Seq2 over index/value pairs.
all := slices.All([]string{"a", "b", "c"})
seq := itu.Take2(all, 2)
for i, v := range seq {
fmt.Printf("%d:%s\n", i, v)
}
}
Output: 0:a 1:b
func TakeWhile ¶ added in v0.7.1
TakeWhile returns a lazy iterator that yields elements from seq while pred returns true.
It yields consecutive values from seq until pred returns false for a value. As soon as pred returns false, iteration stops and that value is not yielded.
Values are tested and produced only as the returned iterator is consumed.
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
seq := slices.Values([]int{10, 11, 12, 13, 14, 15})
out := slices.Collect(itu.TakeWhile(seq, func(v int) bool { return v <= 12 }))
fmt.Println(out)
}
Output: [10 11 12]
func TakeWhile2 ¶ added in v0.7.1
TakeWhile2 returns a lazy iterator that yields pairs (k, v) from seq while pred returns true.
It yields consecutive pairs from seq until pred returns false for a pair. As soon as pred returns false, iteration stops and that pair is not yielded.
Pairs are tested and produced only as the returned iterator is consumed.
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
// slices.All returns an iter.Seq2 over index/value pairs.
all := slices.All([]string{"a", "b", "stop", "c"})
seq := itu.TakeWhile2(all, func(_ int, v string) bool { return v != "stop" })
for i, v := range seq {
fmt.Printf("%d:%s\n", i, v)
}
}
Output: 0:a 1:b
func Zip ¶ added in v0.6.1
Zip returns a lazy iterator that yields pairs (a, b) from seq1 and seq2. The result has the length of the shorter input sequence: iteration stops as soon as either sequence runs out of values (the longer one is truncated).
Example ¶
package main
import (
"fmt"
"slices"
"github.com/lymar/itu"
)
func main() {
longer := slices.Values([]int{1, 2, 3, 4})
shorter := slices.Values([]string{"a", "b"})
for n, s := range itu.Zip(longer, shorter) {
fmt.Printf("%d:%s\n", n, s)
}
}
Output: 1:a 2:b