Documentation
¶
Overview ¶
Package iters provides building blocks for composing iter.Seq and iter.Seq2 pipelines.
Example (Simple_map) ¶
package main
import (
"fmt"
"slices"
"github.com/picatz/iters"
)
func main() {
for v := range iters.Map(
slices.Values(
[]int{1, 2, 3, 4},
),
func(i int) string {
return fmt.Sprintf("%d ", i)
},
) {
fmt.Print(v)
}
}
Output: 1 2 3 4
Example (Simple_map2) ¶
package main
import (
"fmt"
"maps"
"slices"
"github.com/picatz/iters"
)
func main() {
// Use Map2 to transform the input map into a new map
result := maps.Collect(
iters.Map2(
maps.All(
map[string]int{"a": 1, "b": 2, "c": 3},
),
func(k string, v int) (string, int) {
return k + "_new", v * 10
},
),
)
// For stable output, sort the keys of the resulting map
// so we can iterate over the result map in a stable order.
resultKeys := slices.Collect(maps.Keys(result))
slices.Sort(resultKeys)
// Collect and print the results in sorted order
for _, k := range resultKeys {
// Print each key-value pair in the new map
fmt.Printf("%s: %d ", k, result[k])
}
}
Output: a_new: 10 b_new: 20 c_new: 30
Index ¶
- func After[T any](seq iter.Seq[T], n int) iter.Seq[T]
- func AfterFunc[T any](seq iter.Seq[T], pred Predicate[T]) iter.Seq[T]
- func Average[T Number](seq iter.Seq[T]) float64
- func AverageFunc[T any](seq iter.Seq[T], fn func(T) float64) float64
- func Before[T any](seq iter.Seq[T], n int) iter.Seq[T]
- func BeforeFunc[T any](seq iter.Seq[T], pred Predicate[T]) iter.Seq[T]
- func Chunk[T any](seq iter.Seq[T], size int) iter.Seq[[]T]
- func Chunk2[K, V any](seq2 iter.Seq2[K, V], size int) iter.Seq2[[]K, []V]
- func ChunkFunc[T any](seq iter.Seq[T], pred Predicate[T]) iter.Seq[[]T]
- func ChunkFunc2[K, V any](seq2 iter.Seq2[K, V], pred Predicate2[K, V]) iter.Seq2[[]K, []V]
- func CollectErr[T any](seq iter.Seq2[T, error]) ([]T, error)
- func Compact[T comparable](seq iter.Seq[T]) iter.Seq[T]
- func Compact2[K comparable, V comparable](seq2 iter.Seq2[K, V]) iter.Seq2[K, V]
- func CompactFunc[T any](seq iter.Seq[T], equal func(a, b T) bool) iter.Seq[T]
- func CompactFunc2[K, V any](seq2 iter.Seq2[K, V], equal func(aK K, aV V, bK K, bV V) bool) iter.Seq2[K, V]
- func Compare[T cmp.Ordered](s1, s2 iter.Seq[T]) int
- func CompareFunc[T1, T2 any](s1 iter.Seq[T1], s2 iter.Seq[T2], cmp func(T1, T2) int) int
- func Concat[T any](seqs ...iter.Seq[T]) iter.Seq[T]
- func Concat2[K, V any](seqs2 ...iter.Seq2[K, V]) iter.Seq2[K, V]
- func Contains[V comparable](seq iter.Seq[V], value V) bool
- func Contains2[K comparable, V comparable](seq2 iter.Seq2[K, V], key K, value V) bool
- func ContainsFunc[V any](seq iter.Seq[V], fn Predicate[V]) bool
- func ContainsFunc2[K, V any](seq2 iter.Seq2[K, V], fn Predicate2[K, V]) bool
- func Context[T any](ctx context.Context, seq iter.Seq[T]) iter.Seq[T]
- func Context2[K, V any](ctx context.Context, seq2 iter.Seq2[K, V]) iter.Seq2[K, V]
- func Equal[T comparable](seq1, seq2 iter.Seq[T]) bool
- func Equal2[K comparable, V comparable](seq1, seq2 iter.Seq2[K, V]) bool
- func EqualFunc[T any](seq1, seq2 iter.Seq[T], equal func(T, T) bool) bool
- func EqualFunc2[K any, V any](seq1, seq2 iter.Seq2[K, V], equal func(K, V, K, V) bool) bool
- func Filter[V any](seq iter.Seq[V], fn Predicate[V]) iter.Seq[V]
- func Filter2[K, V any](seq2 iter.Seq2[K, V], fn Predicate2[K, V]) iter.Seq2[K, V]
- func First[T any](seq iter.Seq[T]) (first T, ok bool)
- func First2[K, V any](seq2 iter.Seq2[K, V]) (firstK K, firstV V, ok bool)
- func FirstFunc[T any](seq iter.Seq[T], pred Predicate[T]) (first T, ok bool)
- func FirstFunc2[K, V any](seq2 iter.Seq2[K, V], pred Predicate2[K, V]) (firstK K, firstV V, ok bool)
- func Last[T any](seq iter.Seq[T]) (last T, ok bool)
- func Last2[K, V any](seq2 iter.Seq2[K, V]) (lastK K, lastV V, ok bool)
- func LastFunc[T any](seq iter.Seq[T], pred Predicate[T]) (last T, ok bool)
- func LastFunc2[K, V any](seq2 iter.Seq2[K, V], pred Predicate2[K, V]) (lastK K, lastV V, ok bool)
- func Limit[T any](seq iter.Seq[T], n int) iter.Seq[T]
- func Limit2[K, V any](seq2 iter.Seq2[K, V], n int) iter.Seq2[K, V]
- func Map[T, R any](seq iter.Seq[T], fn Mapper[T, R]) iter.Seq[R]
- func Map2[K1, V1, K2, V2 any](seq2 iter.Seq2[K1, V1], fn Mapper2[K1, V1, K2, V2]) iter.Seq2[K2, V2]
- func Max[T cmp.Ordered](seq iter.Seq[T]) (max T, ok bool)
- func MaxFunc[T any](seq iter.Seq[T], less func(a, b T) bool) (max T, ok bool)
- func Min[T cmp.Ordered](seq iter.Seq[T]) (min T, ok bool)
- func MinFunc[T any](seq iter.Seq[T], less func(a, b T) bool) (min T, ok bool)
- func Reduce[T, R any](seq iter.Seq[T], fn func(R, T) R, initial R) R
- func Reduce2[K, V, R any](seq2 iter.Seq2[K, V], fn func(R, K, V) R, initial R) R
- func Repeat[T any](value T) iter.Seq[T]
- func RepeatFunc[T any](fn func() T) iter.Seq[T]
- func RepeatN[T any](value T, count int) iter.Seq[T]
- func Reusable[T any](seq iter.Seq[T]) iter.Seq[T]
- func Reusable2[K, V any](seq2 iter.Seq2[K, V]) iter.Seq2[K, V]
- func Sort[T cmp.Ordered](seq iter.Seq[T]) iter.Seq[T]
- func SortFunc[T any](seq iter.Seq[T], cmp func(a T, b T) int) iter.Seq[T]
- func Split[K, V any](ctx context.Context, seq2 iter.Seq2[K, V]) (iter.Seq[K], iter.Seq[V])
- func Stop[T comparable](seq iter.Seq[T], stop func(T) bool) iter.Seq[T]
- func Stop2[K, V comparable](seq iter.Seq2[K, V], stop func(K, V) bool) iter.Seq2[K, V]
- func Unique[T comparable](seq iter.Seq[T]) iter.Seq[T]
- func UniqueFunc[T any](seq iter.Seq[T], equal func(a, b T) bool) iter.Seq[T]
- func UntilErr[T any](seq iter.Seq2[T, error]) iter.Seq[T]
- func WalkErr[T any](seq iter.Seq2[T, error], fn func(T) bool) error
- func Zip[T1, T2 any](seq1 iter.Seq[T1], seq2 iter.Seq[T2]) iter.Seq2[T1, T2]
- type Mapper
- type Mapper2
- type Number
- type Predicate
- type Predicate2
- type Reducer
- type Reducer2
Examples ¶
- Package (Simple_map)
- Package (Simple_map2)
- After (Numbers)
- AfterFunc (Threshold)
- Average (Numbers)
- AverageFunc (Lengths)
- Before (Numbers)
- BeforeFunc (UntilEven)
- Chunk (KeyValuePairs)
- Chunk (Numbers)
- ChunkFunc (SplitOnZero)
- ChunkFunc2 (SplitPairs)
- CollectErr (Paginated)
- Compact (Numbers)
- Compact2 (Pairs)
- CompactFunc (CaseInsensitive)
- CompactFunc2 (Pairs)
- Compare (Numbers)
- CompareFunc (IgnoreCase)
- Concat (KeyValuePairs)
- Concat (Numbers)
- Contains (Numbers)
- Contains2 (KeyValuePairs)
- ContainsFunc (Strings)
- ContainsFunc2 (KeyValuePairs)
- Context (Cancel)
- Context2 (Cancel)
- Equal (Numbers)
- Equal2 (Pairs)
- EqualFunc (Numbers)
- EqualFunc2 (Pairs)
- Filter (Numbers)
- Filter (Structs)
- Filter2 (KeyValuePairs)
- First (Value)
- First2 (Pair)
- FirstFunc (Even)
- FirstFunc2 (Match)
- Last (Value)
- Last2 (Pair)
- LastFunc (Gt)
- LastFunc2 (Match)
- Limit (KeyValuePairs)
- Limit (Numbers)
- Max (Numbers)
- MaxFunc (Custom)
- Min (Numbers)
- MinFunc (Custom)
- Reduce (Sum)
- Reduce2 (Collect)
- Repeat (Value)
- RepeatFunc (Counter)
- RepeatN (Value)
- Reusable (Twice)
- Reusable2 (Pairs)
- Sort (Numbers)
- SortFunc (Reverse)
- Split (Map)
- Stop (Iteration)
- Stop2 (Pairs)
- Unique (Numbers)
- UniqueFunc (CaseInsensitive)
- UntilErr
- WalkErr
- Zip (Sequences)
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func After ¶
After returns a sequence that discards the first n elements from seq before yielding the remainder. If n is zero or negative the original sequence is yielded unchanged. If n is larger than the number of elements the resulting sequence is empty.
Example (Numbers) ¶
package main
import (
"fmt"
"slices"
"github.com/picatz/iters"
)
func main() {
numbers := []int{1, 2, 3, 4, 5}
afterTwo := iters.After(slices.Values(numbers), 2)
fmt.Println(slices.Collect(afterTwo))
}
Output: [3 4 5]
func AfterFunc ¶
AfterFunc returns a sequence that drops elements from seq while pred reports true. The first element for which pred returns false and all subsequent elements are yielded. If pred never returns false, nothing is produced.
Example (Threshold) ¶
package main
import (
"fmt"
"slices"
"github.com/picatz/iters"
)
func main() {
numbers := []int{1, 3, 2, 4, 5}
afterSmall := iters.AfterFunc(
slices.Values(numbers),
func(v int) bool { return v < 3 },
)
fmt.Println(slices.Collect(afterSmall))
}
Output: [3 2 4 5]
func Average ¶
Average returns the arithmetic mean of seq. It returns 0 when seq contains no values.
Example (Numbers) ¶
package main
import (
"fmt"
"slices"
"github.com/picatz/iters"
)
func main() {
values := []int{2, 4, 6, 8}
fmt.Println(iters.Average(slices.Values(values)))
}
Output: 5
func AverageFunc ¶
AverageFunc computes the arithmetic mean of fn(item) for every element in seq. It returns 0 when seq is empty.
Example (Lengths) ¶
package main
import (
"fmt"
"slices"
"github.com/picatz/iters"
)
func main() {
words := []string{"go", "iters"}
fmt.Println(
iters.AverageFunc(
slices.Values(words),
func(s string) float64 { return float64(len(s)) },
),
)
}
Output: 3.5
func Before ¶
Before returns a sequence that yields at most n elements from seq. If seq is shorter than n the entire input is passed through.
Example (Numbers) ¶
package main
import (
"fmt"
"slices"
"github.com/picatz/iters"
)
func main() {
numbers := []int{1, 2, 3, 4, 5}
beforeThree := iters.Before(slices.Values(numbers), 3)
fmt.Println(slices.Collect(beforeThree))
}
Output: [1 2 3]
func BeforeFunc ¶
BeforeFunc returns a sequence that yields elements from seq until pred first returns true. The matching element is not forwarded. If pred never returns true the entire input is yielded.
Example (UntilEven) ¶
package main
import (
"fmt"
"slices"
"github.com/picatz/iters"
)
func main() {
numbers := []int{1, 3, 5, 4, 7}
beforeEven := iters.BeforeFunc(
slices.Values(numbers),
func(v int) bool { return v%2 == 0 },
)
fmt.Println(slices.Collect(beforeEven))
}
Output: [1 3 5]
func Chunk ¶
Chunk groups seq into contiguous slices of length size and returns a new sequence that yields those slices in order. The final chunk may be shorter if the input length is not divisible by size. When size <= 0 no chunks are produced.
Example (KeyValuePairs) ¶
package main
import (
"fmt"
"maps"
"slices"
"github.com/picatz/iters"
)
func main() {
dictionary := map[string]string{
"apple": "A fruit",
"banana": "Another fruit",
"carrot": "A vegetable",
"date": "A sweet fruit",
"egg": "A protein source",
}
chunkSize := 2
keys := slices.Collect(maps.Keys(dictionary))
slices.Sort(keys)
chunked := iters.Chunk2(
func(yield func(string, string) bool) {
for _, key := range keys {
if !yield(key, dictionary[key]) {
return
}
}
},
chunkSize,
)
resultKeys := [][]string{}
resultValues := [][]string{}
for keys, values := range chunked {
resultKeys = append(resultKeys, keys)
resultValues = append(resultValues, values)
}
fmt.Printf("%q\n", resultKeys)
fmt.Printf("%q\n", resultValues)
}
Output: [["apple" "banana"] ["carrot" "date"] ["egg"]] [["A fruit" "Another fruit"] ["A vegetable" "A sweet fruit"] ["A protein source"]]
Example (Numbers) ¶
package main
import (
"fmt"
"slices"
"github.com/picatz/iters"
)
func main() {
numbers := []int{1, 2, 3, 4, 5, 6, 7}
chunkSize := 3
chunked := iters.Chunk(
slices.Values(numbers),
chunkSize,
)
result := slices.Collect(chunked)
fmt.Println(result)
}
Output: [[1 2 3] [4 5 6] [7]]
func Chunk2 ¶
Chunk2 is the keyed companion to Chunk; it groups seq2 into slices of keys and values with the requested size. The final chunk may be shorter. When size <= 0 no chunks are produced.
func ChunkFunc ¶
ChunkFunc groups seq into slices, starting a new chunk each time pred returns true for an element. The matching element begins the next chunk. Any partial chunk is yielded when seq is exhausted.
Example (SplitOnZero) ¶
package main
import (
"fmt"
"slices"
"github.com/picatz/iters"
)
func main() {
values := []int{1, 2, 0, 3, 4, 0, 5}
chunks := iters.ChunkFunc(
slices.Values(values),
func(v int) bool { return v == 0 },
)
fmt.Println(slices.Collect(chunks))
}
Output: [[1 2] [0 3 4] [0 5]]
func ChunkFunc2 ¶
ChunkFunc2 is the keyed companion to ChunkFunc; it starts a fresh chunk when pred reports true for a key/value pair. The matching pair becomes the first element of the next chunk.
Example (SplitPairs) ¶
package main
import (
"fmt"
"github.com/picatz/iters"
)
func main() {
seq2 := func(yield func(string, int) bool) {
data := []struct {
Key string
Val int
}{
{"a", 1},
{"b", 2},
{"b", 3},
{"c", 4},
}
for _, item := range data {
if !yield(item.Key, item.Val) {
return
}
}
}
chunks := iters.ChunkFunc2(
seq2,
func(k string, _ int) bool { return k == "b" },
)
for keys, values := range chunks {
fmt.Printf("%q %v\n", keys, values)
}
}
Output: ["a"] [1] ["b"] [2] ["b" "c"] [3 4]
func CollectErr ¶
CollectErr gathers values from seq until a non-nil error occurs. It returns the values seen so far along with the first error, or nil if seq completed.
Example (Paginated) ¶
package main
import (
"fmt"
"github.com/picatz/iters"
)
func main() {
type page struct {
items []int
err error
}
pages := []page{
{items: []int{1, 2}},
{items: []int{3}},
}
seq := func(yield func(int, error) bool) {
for _, p := range pages {
for _, item := range p.items {
if !yield(item, nil) {
return
}
}
}
}
values, err := iters.CollectErr(seq)
fmt.Println(values, err)
}
Output: [1 2 3] <nil>
func Compact ¶
func Compact[T comparable](seq iter.Seq[T]) iter.Seq[T]
Compact collapses consecutive duplicate elements in seq, yielding the first element of each run.
Example (Numbers) ¶
package main
import (
"fmt"
"slices"
"github.com/picatz/iters"
)
func main() {
seq := iters.Compact(slices.Values([]int{1, 1, 2, 2, 3, 1}))
fmt.Println(slices.Collect(seq))
}
Output: [1 2 3 1]
func Compact2 ¶
func Compact2[K comparable, V comparable](seq2 iter.Seq2[K, V]) iter.Seq2[K, V]
Compact2 collapses consecutive duplicate key/value pairs in seq2, yielding the first pair from each run.
Example (Pairs) ¶
package main
import (
"fmt"
"github.com/picatz/iters"
)
func main() {
seq2 := func(yield func(string, int) bool) {
pairs := []struct {
key string
val int
}{
{"a", 1},
{"a", 1},
{"b", 2},
{"b", 2},
}
for _, p := range pairs {
if !yield(p.key, p.val) {
return
}
}
}
var keys []string
var values []int
for k, v := range iters.Compact2(seq2) {
keys = append(keys, k)
values = append(values, v)
}
fmt.Println(keys)
fmt.Println(values)
}
Output: [a b] [1 2]
func CompactFunc ¶
CompactFunc collapses consecutive elements in seq for which equal reports true, yielding only the first element of each run.
Example (CaseInsensitive) ¶
package main
import (
"fmt"
"slices"
"strings"
"github.com/picatz/iters"
)
func main() {
seq := iters.CompactFunc(
slices.Values([]string{"Go", "go", "iters", "ITERS"}),
func(a, b string) bool { return strings.EqualFold(a, b) },
)
fmt.Println(slices.Collect(seq))
}
Output: [Go iters]
func CompactFunc2 ¶
func CompactFunc2[K, V any](seq2 iter.Seq2[K, V], equal func(aK K, aV V, bK K, bV V) bool) iter.Seq2[K, V]
CompactFunc2 collapses consecutive key/value pairs in seq2 for which equal reports true, yielding the first pair of each run.
Example (Pairs) ¶
package main
import (
"fmt"
"strings"
"github.com/picatz/iters"
)
func main() {
seq2 := func(yield func(string, string) bool) {
pairs := []struct {
key string
val string
}{
{"a", "One"},
{"a", "one"},
{"b", "Two"},
}
for _, p := range pairs {
if !yield(p.key, p.val) {
return
}
}
}
var keys []string
var values []string
for k, v := range iters.CompactFunc2(
seq2,
func(k1, v1, k2, v2 string) bool {
return strings.EqualFold(k1, k2) && strings.EqualFold(v1, v2)
},
) {
keys = append(keys, k)
values = append(values, v)
}
fmt.Println(keys)
fmt.Println(values)
}
Output: [a b] [One Two]
func Compare ¶
Compare returns -1, 0, or +1 depending on the lexicographic ordering of s1 and s2, matching slices.Compare semantics. Elements are compared with cmp.Compare until a difference is found or one sequence ends.
Example (Numbers) ¶
package main
import (
"fmt"
"slices"
"github.com/picatz/iters"
)
func main() {
a := slices.Values([]int{1, 2, 3})
b := slices.Values([]int{1, 2, 4})
fmt.Println(iters.Compare(a, b))
}
Output: -1
func CompareFunc ¶
CompareFunc behaves like Compare but calls cmp for each pair of elements. The first non-zero result is returned, otherwise the shorter sequence sorts before the longer one.
Example (IgnoreCase) ¶
package main
import (
"fmt"
"slices"
"strings"
"github.com/picatz/iters"
)
func main() {
a := slices.Values([]string{"Go", "iters"})
b := slices.Values([]string{"go", "Iters"})
fmt.Println(
iters.CompareFunc(
a,
b,
func(x, y string) int {
xLower := strings.ToLower(x)
yLower := strings.ToLower(y)
switch {
case xLower < yLower:
return -1
case xLower > yLower:
return 1
default:
return 0
}
},
),
)
}
Output: 0
func Concat ¶
Concat returns a sequence that yields every element from seqs in order. Iteration stops early if the consumer stops pulling values.
Example (KeyValuePairs) ¶
package main
import (
"fmt"
"maps"
"github.com/picatz/iters"
)
func main() {
map1 := map[string]int{
"one": 1,
"two": 2,
}
map2 := map[string]int{
"three": 3,
"four": 4,
}
concatenated := iters.Concat2(
maps.All(map1),
maps.All(map2),
)
result := maps.Collect(concatenated)
fmt.Println(result["one"], result["two"], result["three"], result["four"])
}
Output: 1 2 3 4
Example (Numbers) ¶
package main
import (
"fmt"
"slices"
"github.com/picatz/iters"
)
func main() {
seq1 := []int{1, 2, 3}
seq2 := []int{4, 5, 6}
concatenated := iters.Concat(
slices.Values(seq1),
slices.Values(seq2),
)
result := slices.Collect(concatenated)
fmt.Println(result)
}
Output: [1 2 3 4 5 6]
func Contains ¶
func Contains[V comparable](seq iter.Seq[V], value V) bool
Contains reports whether value appears in seq.
Example (Numbers) ¶
package main
import (
"fmt"
"slices"
"github.com/picatz/iters"
)
func main() {
numbers := []int{1, 2, 3, 4, 5}
hasThree := iters.Contains(
slices.Values(numbers),
3,
)
hasSix := iters.Contains(
slices.Values(numbers),
6,
)
fmt.Println(hasThree)
fmt.Println(hasSix)
}
Output: true false
func Contains2 ¶
func Contains2[K comparable, V comparable](seq2 iter.Seq2[K, V], key K, value V) bool
Contains2 reports whether the pair (key, value) appears in seq2.
Example (KeyValuePairs) ¶
package main
import (
"fmt"
"maps"
"github.com/picatz/iters"
)
func main() {
dictionary := map[string]string{
"apple": "A fruit",
"banana": "Another fruit",
"carrot": "A vegetable",
}
hasAppleDefinition := iters.Contains2(
maps.All(dictionary),
"apple",
"A fruit",
)
hasBananaWrongDefinition := iters.Contains2(
maps.All(dictionary),
"banana",
"A yellow fruit",
)
fmt.Println(hasAppleDefinition)
fmt.Println(hasBananaWrongDefinition)
}
Output: true false
func ContainsFunc ¶
ContainsFunc reports whether any element in seq satisfies fn.
Example (Strings) ¶
package main
import (
"fmt"
"slices"
"github.com/picatz/iters"
)
func main() {
fruit := []string{"apple", "banana", "cherry", "date"}
hasLongString := iters.ContainsFunc(
slices.Values(fruit),
func(s string) bool {
return len(s) > 5
},
)
hasBString := iters.ContainsFunc(
slices.Values(fruit),
func(s string) bool {
return s[0] == 'b'
},
)
fmt.Println(hasLongString)
fmt.Println(hasBString)
}
Output: true true
func ContainsFunc2 ¶
func ContainsFunc2[K, V any](seq2 iter.Seq2[K, V], fn Predicate2[K, V]) bool
ContainsFunc2 reports whether any key/value pair in seq2 satisfies fn.
Example (KeyValuePairs) ¶
package main
import (
"fmt"
"maps"
"github.com/picatz/iters"
)
func main() {
dictionary := map[string]string{
"apple": "A fruit",
"banana": "Another fruit",
"carrot": "A vegetable",
}
hasDefinitionWithA := iters.ContainsFunc2(
maps.All(dictionary),
func(k, v string) bool {
return v[0] == 'A'
},
)
hasDefinitionWithZ := iters.ContainsFunc2(
maps.All(dictionary),
func(k, v string) bool {
return v[0] == 'Z'
},
)
fmt.Println(hasDefinitionWithA)
fmt.Println(hasDefinitionWithZ)
}
Output: true false
func Context ¶
Context returns a sequence that yields values from seq until ctx is canceled or seq finishes. Cancellation is checked between elements.
Example (Cancel) ¶
package main
import (
"context"
"fmt"
"slices"
"github.com/picatz/iters"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
seq := iters.Context(
ctx,
func(yield func(int) bool) {
for i := 1; i <= 5; i++ {
if i == 3 {
cancel()
}
if !yield(i) {
return
}
}
},
)
fmt.Println(slices.Collect(seq))
}
Output: [1 2]
func Context2 ¶
Context2 returns a sequence of key/value pairs from seq2 that stops yielding as soon as ctx is canceled.
Example (Cancel) ¶
package main
import (
"context"
"fmt"
"github.com/picatz/iters"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
seq2 := func(yield func(string, int) bool) {
pairs := []struct {
key string
val int
}{
{"a", 1},
{"b", 2},
{"c", 3},
}
for _, pair := range pairs {
if pair.key == "b" {
cancel()
}
if !yield(pair.key, pair.val) {
return
}
}
}
ctxSeq := iters.Context2(ctx, seq2)
var keys []string
for k := range ctxSeq {
keys = append(keys, k)
}
fmt.Println(keys)
}
Output: [a]
func Equal ¶
func Equal[T comparable](seq1, seq2 iter.Seq[T]) bool
Equal reports whether seq1 and seq2 yield the same elements in the same order. Iteration stops as soon as a mismatch is found.
Example (Numbers) ¶
package main
import (
"fmt"
"slices"
"github.com/picatz/iters"
)
func main() {
a := slices.Values([]int{1, 2, 3})
b := slices.Values([]int{1, 2, 3})
fmt.Println(iters.Equal(a, b))
}
Output: true
func Equal2 ¶
func Equal2[K comparable, V comparable](seq1, seq2 iter.Seq2[K, V]) bool
Equal2 reports whether two sequences of key/value pairs yield identical pairs in the same order.
Example (Pairs) ¶
package main
import (
"fmt"
"github.com/picatz/iters"
)
func main() {
seq := func(yield func(string, int) bool) {
pairs := []struct {
key string
val int
}{
{"a", 1},
{"b", 2},
}
for _, pair := range pairs {
if !yield(pair.key, pair.val) {
return
}
}
}
fmt.Println(iters.Equal2(seq, seq))
}
Output: true
func EqualFunc ¶
EqualFunc reports whether seq1 and seq2 yield elements that are equal according to equal. The sequences must produce the same number of items.
Example (Numbers) ¶
package main
import (
"fmt"
"math"
"slices"
"github.com/picatz/iters"
)
func main() {
a := slices.Values([]float64{1, 2, math.NaN()})
b := slices.Values([]float64{1, 2, math.NaN()})
fmt.Println(
iters.EqualFunc(
a,
b,
func(x, y float64) bool {
if math.IsNaN(x) && math.IsNaN(y) {
return true
}
return x == y
},
),
)
}
Output: true
func EqualFunc2 ¶
EqualFunc2 reports whether seq1 and seq2 produce key/value pairs that are equal according to equal. The sequences must yield the same number of pairs.
Example (Pairs) ¶
package main
import (
"fmt"
"github.com/picatz/iters"
)
func main() {
seq := func(yield func(string, int) bool) {
pairs := []struct {
key string
val int
}{
{"a", 1},
{"b", 2},
}
for _, pair := range pairs {
if !yield(pair.key, pair.val) {
return
}
}
}
fmt.Println(
iters.EqualFunc2(
seq,
seq,
func(k1 string, v1 int, k2 string, v2 int) bool {
return k1 == k2 && v1 == v2
},
),
)
}
Output: true
func Filter ¶
Filter returns a sequence that yields only the elements of seq that make fn return true.
Example (Numbers) ¶
package main
import (
"fmt"
"slices"
"github.com/picatz/iters"
)
func main() {
// Example usage of the Filter function to filter a slice of integers.
numbers := []int{1, 2, 3, 4, 5}
// Define the filter function to keep only odd numbers.
oddNumbers := iters.Filter(
// Convert the slice to an iter.Seq[int]
slices.Values(numbers),
func(num int) bool {
return num%2 != 0 // Keep only odd numbers
},
)
// Collect the filtered results into a slice.
result := slices.Collect(oddNumbers)
fmt.Println(result)
}
Output: [1 3 5]
Example (Structs) ¶
package main
import (
"fmt"
"slices"
"github.com/picatz/iters"
)
func main() {
// Example usage of the Filter function to filter a slice of structs,
// which are animals with a name and number of legs in this case.
type Animal struct {
Name string
Legs int
}
animals := []Animal{
{"cat", 4},
{"dog", 4},
{"fish", 0},
{"bird", 2},
}
// Define the filter function to keep only animals with more than 2 legs.
filteredAnimals := iters.Filter(
// Convert the slice to an iter.Seq[Animal]
slices.Values(animals),
func(animal Animal) bool {
return animal.Legs > 2 // Keep animals with more than 2 legs
},
)
// Collect the filtered results into a slice.
result := slices.Collect(filteredAnimals)
fmt.Println(result)
}
Output: [{cat 4} {dog 4}]
func Filter2 ¶
Filter2 is the keyed companion to Filter; it forwards only the pairs from seq2 that satisfy fn.
Example (KeyValuePairs) ¶
package main
import (
"fmt"
"maps"
"github.com/picatz/iters"
)
func main() {
fruits := map[string]string{
"apple": "fruit",
"carrot": "vegetable",
"pear": "fruit",
}
filtered := iters.Filter2(
maps.All(fruits),
func(key, value string) bool {
return value == "fruit" && key != "pear"
},
)
fmt.Println(maps.Collect(filtered))
}
Output: map[apple:fruit]
func First ¶
First returns the first element produced by seq. If seq yields nothing, ok is false and the zero value is returned.
Example (Value) ¶
package main
import (
"fmt"
"slices"
"github.com/picatz/iters"
)
func main() {
fmt.Println(iters.First(slices.Values([]int{4, 5, 6})))
}
Output: 4 true
func First2 ¶
First2 returns the first key/value pair from seq2. If seq2 yields no pairs, ok is false.
Example (Pair) ¶
package main
import (
"fmt"
"github.com/picatz/iters"
)
func main() {
seq2 := func(yield func(string, int) bool) {
if !yield("a", 1) {
return
}
}
k, v, ok := iters.First2(seq2)
fmt.Println(k, v, ok)
}
Output: a 1 true
func FirstFunc ¶
FirstFunc returns the first element of seq that satisfies pred. If no element matches, ok is false.
Example (Even) ¶
package main
import (
"fmt"
"slices"
"github.com/picatz/iters"
)
func main() {
firstEven, ok := iters.FirstFunc(
slices.Values([]int{1, 3, 4, 5}),
func(v int) bool { return v%2 == 0 },
)
fmt.Println(firstEven, ok)
}
Output: 4 true
func FirstFunc2 ¶
func FirstFunc2[K, V any](seq2 iter.Seq2[K, V], pred Predicate2[K, V]) (firstK K, firstV V, ok bool)
FirstFunc2 returns the first pair from seq2 that satisfies pred. If no pair matches, ok is false.
Example (Match) ¶
package main
import (
"fmt"
"github.com/picatz/iters"
)
func main() {
seq2 := func(yield func(string, int) bool) {
pairs := []struct {
key string
val int
}{
{"a", 1},
{"b", 3},
{"c", 4},
}
for _, pair := range pairs {
if !yield(pair.key, pair.val) {
return
}
}
}
k, v, ok := iters.FirstFunc2(seq2, func(_ string, val int) bool { return val%2 == 0 })
fmt.Println(k, v, ok)
}
Output: c 4 true
func Last ¶
Last returns the final element produced by seq. If seq yields nothing, ok is false.
Example (Value) ¶
package main
import (
"fmt"
"slices"
"github.com/picatz/iters"
)
func main() {
fmt.Println(iters.Last(slices.Values([]int{1, 2, 3})))
}
Output: 3 true
func Last2 ¶
Last2 returns the final key/value pair produced by seq2. If seq2 yields nothing, ok is false.
Example (Pair) ¶
package main
import (
"fmt"
"github.com/picatz/iters"
)
func main() {
seq2 := func(yield func(string, int) bool) {
data := []struct {
key string
val int
}{
{"a", 1},
{"b", 2},
}
for _, pair := range data {
if !yield(pair.key, pair.val) {
return
}
}
}
k, v, ok := iters.Last2(seq2)
fmt.Println(k, v, ok)
}
Output: b 2 true
func LastFunc ¶
LastFunc returns the final element of seq that satisfies pred. If no element matches, ok is false.
Example (Gt) ¶
package main
import (
"fmt"
"slices"
"github.com/picatz/iters"
)
func main() {
last, ok := iters.LastFunc(
slices.Values([]int{1, 4, 2, 5}),
func(v int) bool { return v > 3 },
)
fmt.Println(last, ok)
}
Output: 5 true
func LastFunc2 ¶
func LastFunc2[K, V any](seq2 iter.Seq2[K, V], pred Predicate2[K, V]) (lastK K, lastV V, ok bool)
LastFunc2 returns the final key/value pair from seq2 that satisfies pred. If no pair matches, ok is false.
Example (Match) ¶
package main
import (
"fmt"
"github.com/picatz/iters"
)
func main() {
seq2 := func(yield func(string, int) bool) {
data := []struct {
key string
val int
}{
{"a", 1},
{"b", 2},
{"c", 3},
}
for _, pair := range data {
if !yield(pair.key, pair.val) {
return
}
}
}
k, v, ok := iters.LastFunc2(seq2, func(_ string, v int) bool { return v >= 2 })
fmt.Println(k, v, ok)
}
Output: c 3 true
func Limit ¶
Limit returns a sequence that yields at most n values from seq. When n is zero or negative the returned sequence is empty.
Example (KeyValuePairs) ¶
package main
import (
"fmt"
"maps"
"slices"
"github.com/picatz/iters"
)
func main() {
dictionary := map[string]string{
"apple": "A fruit",
"banana": "Another fruit",
"carrot": "A vegetable",
"date": "A sweet fruit",
"egg": "A protein source",
}
keys := slices.Collect(maps.Keys(dictionary))
slices.Sort(keys)
limited := iters.Limit2(
func(yield func(string, string) bool) {
for _, key := range keys {
if !yield(key, dictionary[key]) {
return
}
}
},
2,
)
resultKeys := []string{}
resultValues := []string{}
for key, value := range limited {
resultKeys = append(resultKeys, key)
resultValues = append(resultValues, value)
}
fmt.Printf("%q\n", resultKeys)
fmt.Printf("%q\n", resultValues)
}
Output: ["apple" "banana"] ["A fruit" "Another fruit"]
Example (Numbers) ¶
package main
import (
"fmt"
"slices"
"github.com/picatz/iters"
)
func main() {
numbers := []int{1, 2, 3, 4, 5}
limited := iters.Limit(
slices.Values(numbers),
3,
)
result := slices.Collect(limited)
fmt.Println(result)
}
Output: [1 2 3]
func Max ¶
Max returns the largest element produced by seq according to Go's ordering for cmp.Ordered types. If seq is empty, ok is false.
Example (Numbers) ¶
package main
import (
"fmt"
"slices"
"github.com/picatz/iters"
)
func main() {
max, ok := iters.Max(slices.Values([]int{3, 1, 4}))
fmt.Println(max, ok)
}
Output: 4 true
func MaxFunc ¶
MaxFunc returns the element in seq that maximizes the provided less function (a returns true when a < b). If seq is empty, ok is false.
Example (Custom) ¶
package main
import (
"fmt"
"slices"
"github.com/picatz/iters"
)
func main() {
type Item struct {
Name string
Score int
}
items := []Item{{"a", 1}, {"b", 3}}
max, ok := iters.MaxFunc(
slices.Values(items),
func(a, b Item) bool { return a.Score < b.Score },
)
fmt.Println(max, ok)
}
Output: {b 3} true
func Min ¶
Min returns the smallest element produced by seq according to Go's ordering for cmp.Ordered types. If seq is empty, ok is false.
Example (Numbers) ¶
package main
import (
"fmt"
"slices"
"github.com/picatz/iters"
)
func main() {
min, ok := iters.Min(slices.Values([]int{3, 1, 4}))
fmt.Println(min, ok)
}
Output: 1 true
func MinFunc ¶
MinFunc returns the element in seq that minimizes the provided less function. If seq is empty, ok is false.
Example (Custom) ¶
package main
import (
"fmt"
"slices"
"github.com/picatz/iters"
)
func main() {
type Item struct {
Name string
Score int
}
items := []Item{{"a", 1}, {"b", 3}}
min, ok := iters.MinFunc(
slices.Values(items),
func(a, b Item) bool { return a.Score < b.Score },
)
fmt.Println(min, ok)
}
Output: {a 1} true
func Reduce ¶
Reduce folds seq into a single value by repeatedly applying fn to the accumulator and the next element. The initial value is returned unchanged if seq is empty.
Example (Sum) ¶
package main
import (
"fmt"
"slices"
"github.com/picatz/iters"
)
func main() {
// Example usage of the Reduce function to sum a slice of integers.
numbers := []int{1, 2, 3, 4, 5}
// Define the reduce function to sum the numbers.
sum := iters.Reduce(
// Convert the slice to an iter.Seq[int]
slices.Values(numbers),
func(acc int, num int) int {
return acc + num // Sum the numbers
},
// Initial value for the sum, which is 0 in this case.
0,
)
fmt.Println(sum)
}
Output: 15
func Reduce2 ¶
Reduce2 folds seq2 into a single value by repeatedly calling fn with the accumulator and the next key/value pair.
Example (Collect) ¶
package main
import (
"fmt"
"maps"
"github.com/picatz/iters"
)
func main() {
input := map[string]int{
"a": 1,
"b": 2,
}
sum := iters.Reduce2(
maps.All(input),
func(acc int, key string, value int) int {
return acc + value
},
0,
)
fmt.Println(sum)
}
Output: 3
func Repeat ¶
Repeat returns an infinite sequence that keeps yielding value until the consumer stops iteration.
Example (Value) ¶
package main
import (
"fmt"
"slices"
"github.com/picatz/iters"
)
func main() {
repeated := iters.Limit(iters.Repeat(7), 3)
fmt.Println(slices.Collect(repeated))
}
Output: [7 7 7]
func RepeatFunc ¶
RepeatFunc returns an infinite sequence that yields the result of fn on every iteration.
Example (Counter) ¶
package main
import (
"fmt"
"slices"
"github.com/picatz/iters"
)
func main() {
counter := 0
repeated := iters.Limit(
iters.RepeatFunc(func() int {
counter++
return counter
}),
3,
)
fmt.Println(slices.Collect(repeated))
}
Output: [1 2 3]
func RepeatN ¶
RepeatN yields value count times. When count <= 0 nothing is produced.
Example (Value) ¶
package main
import (
"fmt"
"slices"
"github.com/picatz/iters"
)
func main() {
fmt.Println(slices.Collect(iters.RepeatN("go", 2)))
}
Output: [go go]
func Reusable ¶
Reusable caches every element pulled from seq so that the returned sequence can be iterated multiple times. The cache grows until seq is exhausted, so using Reusable with an unbounded input can consume unbounded memory.
Example (Twice) ¶
package main
import (
"fmt"
"slices"
"github.com/picatz/iters"
)
func main() {
reusable := iters.Reusable(slices.Values([]int{1, 2, 3}))
first := slices.Collect(reusable)
second := slices.Collect(reusable)
fmt.Println(first, second)
}
Output: [1 2 3] [1 2 3]
func Reusable2 ¶
Reusable2 caches each key/value pair pulled from seq2 so that the result can be iterated multiple times. It shares the same memory trade-offs as Reusable.
Example (Pairs) ¶
package main
import (
"fmt"
"maps"
"github.com/picatz/iters"
)
func main() {
source := map[string]int{"a": 1, "b": 2}
reusable := iters.Reusable2(maps.All(source))
first := maps.Collect(reusable)
second := maps.Collect(reusable)
fmt.Println(first["a"], second["b"])
}
Output: 1 2
func Sort ¶
Sort collects seq into a slice, sorts it in ascending order using the natural ordering for cmp.Ordered types, and returns a sequence that yields the sorted values.
Example (Numbers) ¶
package main
import (
"fmt"
"slices"
"github.com/picatz/iters"
)
func main() {
sorted := slices.Collect(iters.Sort(slices.Values([]int{3, 1, 2})))
fmt.Println(sorted)
}
Output: [1 2 3]
func SortFunc ¶
SortFunc behaves like Sort but orders the elements with cmp, matching slices.SortFunc's contract.
Example (Reverse) ¶
package main
import (
"fmt"
"slices"
"github.com/picatz/iters"
)
func main() {
sorted := slices.Collect(
iters.SortFunc(
slices.Values([]int{1, 2, 3}),
func(a, b int) int { return b - a },
),
)
fmt.Println(sorted)
}
Output: [3 2 1]
func Split ¶
Split duplicates seq2 into two coordinated sequences, one exposing the keys and the other the values. Reads stay synchronized so that each key is paired with its corresponding value even when the consumers progress independently. Iteration stops when ctx is canceled or seq2 finishes.
Example (Map) ¶
package main
import (
"context"
"fmt"
"maps"
"github.com/picatz/iters"
)
func main() {
input := map[int]string{
1: "one",
2: "two",
3: "three",
}
output := make(map[int]string)
maps.Insert(
output,
iters.Zip(
iters.Split(
context.Background(),
maps.All(input),
),
),
)
fmt.Println(maps.Equal(output, input))
}
Output: true
func Stop ¶
Stop returns a sequence that yields values from seq until stop reports true for an element. The matching element is discarded. If stop never returns true the entire input is forwarded.
Example (Iteration) ¶
package main
import (
"fmt"
"slices"
"github.com/picatz/iters"
)
func main() {
// Example usage of the StopIteration function to stop iteration early.
numbers := []int{1, 2, 3, 4, 5}
// Define a function that stops iteration when it encounters the number 3.
stoppedIteration := iters.Stop(
// Convert the slice to an iter.Seq[int]
slices.Values(numbers),
func(num int) bool {
return num == 3 // Stop iteration when the number is 3
},
)
// Collect the results into a slice.
result := slices.Collect(stoppedIteration)
fmt.Println(result)
}
Output: [1 2]
func Stop2 ¶
Stop2 returns a sequence that yields pairs from seq2 until stop reports true for a key/value pair, excluding the matching pair.
Example (Pairs) ¶
package main
import (
"fmt"
"github.com/picatz/iters"
)
func main() {
type pair struct {
key string
val int
}
input := []pair{
{"a", 1},
{"stop", 0},
{"b", 2},
}
seq2 := func(yield func(string, int) bool) {
for _, p := range input {
if !yield(p.key, p.val) {
return
}
}
}
stopped := iters.Stop2(seq2, func(k string, _ int) bool { return k == "stop" })
for k, v := range stopped {
fmt.Println(k, v)
}
}
Output: a 1
func Unique ¶
func Unique[T comparable](seq iter.Seq[T]) iter.Seq[T]
Unique returns a sequence that yields each distinct element from seq once, preserving the first occurrence order. It keeps a set of seen values, so T must be comparable.
Example (Numbers) ¶
package main
import (
"fmt"
"slices"
"github.com/picatz/iters"
)
func main() {
fmt.Println(slices.Collect(iters.Unique(slices.Values([]int{1, 2, 2, 3}))))
}
Output: [1 2 3]
func UniqueFunc ¶
UniqueFunc behaves like Unique but determines equality with equal, allowing use with non-comparable types.
Example (CaseInsensitive) ¶
package main
import (
"fmt"
"slices"
"strings"
"github.com/picatz/iters"
)
func main() {
words := []string{"Go", "go", "iters"}
unique := iters.UniqueFunc(
slices.Values(words),
func(a, b string) bool { return strings.EqualFold(a, b) },
)
fmt.Println(slices.Collect(unique))
}
Output: [Go iters]
func UntilErr ¶
UntilErr converts seq into a plain sequence that yields values until a non-nil error appears. The error-causing element is discarded.
Example ¶
package main
import (
"errors"
"fmt"
"slices"
"github.com/picatz/iters"
)
func main() {
seq := func(yield func(int, error) bool) {
if !yield(1, nil) {
return
}
if !yield(0, errors.New("boom")) {
return
}
if !yield(2, nil) {
return
}
}
fmt.Println(slices.Collect(iters.UntilErr(seq)))
}
Output: [1]
func WalkErr ¶
WalkErr iterates over seq, invoking fn for each value until either fn returns false or seq yields a non-nil error. The first error encountered is returned.
Example ¶
package main
import (
"fmt"
"github.com/picatz/iters"
)
func main() {
seq := func(yield func(string, error) bool) {
for _, word := range []string{"hello", "iter"} {
if !yield(word, nil) {
return
}
}
}
_ = iters.WalkErr(seq, func(s string) bool {
fmt.Println(s)
return true
})
}
Output: hello iter
func Zip ¶
Zip returns a sequence of pairs formed by reading seq1 and seq2 in lockstep. Iteration stops when either input sequence ends.
Example (Sequences) ¶
package main
import (
"fmt"
"slices"
"github.com/picatz/iters"
)
func main() {
seq := iters.Zip(
slices.Values([]int{1, 2}),
slices.Values([]string{"a", "b"}),
)
for n, s := range seq {
fmt.Println(n, s)
}
}
Output: 1 a 2 b
Types ¶
type Mapper2 ¶
type Mapper2[K1, V1, K2, V2 any] = func(K1, V1) (K2, V2)
Mapper2 describes the transformation applied by Map2.
type Number ¶
type Number interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 |
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
~float32 | ~float64
}
Number matches any built-in integer or floating-point type.
type Predicate2 ¶
Predicate2 is the keyed counterpart to Predicate.