itertools

package
v0.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 20, 2025 License: BSD-3-Clause Imports: 6 Imported by: 1

Documentation

Overview

Package itertools provides tools or working with sequences as defined in iter. It is inspired by the Python itertools package

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Accumulate

func Accumulate[V1 any, V2 any](
	seq iter.Seq[V1],
	function func(acc V2, val V1) V2,
	initial V2,
) iter.Seq[V2]

Accumulate returns a iter.Seq that returns accumulated results from function. The function should accept two arguments, an accumulated total and a value from the input sequence.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	seq := slices.Values([]int{1, 2, 3, 4, 5})
	add := func(x int, y int) int { return x + y }

	for v := range itertools.Accumulate(seq, add, 0) {
		fmt.Println(v)
	}

}
Output:

1
3
6
10
15
Example (MixedTypes)
package main

import (
	"fmt"
	"slices"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	seq := slices.Values([]int{1, 2, 3, 4, 5})
	add := func(c complex64, x int) complex64 { return c + complex(float32(x), 1.0) }

	for s := range itertools.Accumulate(seq, add, 0) {
		fmt.Println(s)
	}

}
Output:

(1+1i)
(3+2i)
(6+3i)
(10+4i)
(15+5i)

func AllFunc

func AllFunc[V any](checker func(V) bool, seq iter.Seq[V]) bool

AllFunc returns true if checker returns true for all values in seq otherwise it returns false.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	seq := slices.Values([]int{1, 2, 3, 4, 5})

	fmt.Println(itertools.AllFunc(func(i int) bool { return i > 0 }, seq))
	fmt.Println(itertools.AllFunc(func(i int) bool { return i < 0 }, seq))
	fmt.Println(itertools.AllFunc(func(i int) bool { return i < 4 }, seq))

}
Output:

true
false
false

func AllFunc2

func AllFunc2[K comparable, V any](checker func(K, V) bool, seq iter.Seq2[K, V]) bool

AllFunc2 returns true if checker returns true for all values in seq otherwise it returns false.

Example
package main

import (
	"fmt"
	"maps"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	seq := maps.All(map[string]int{"a": 1, "b": 2, "c": 3})

	fmt.Println(itertools.AllFunc2(func(k string, v int) bool { return k < "d" && v < 4 }, seq))
	fmt.Println(itertools.AllFunc2(func(k string, v int) bool { return k > "d" || v < 4 }, seq))
	fmt.Println(itertools.AllFunc2(func(k string, v int) bool { return k > "d" && v > 4 }, seq))

}
Output:

true
true
false

func AnyFunc

func AnyFunc[V any](checker func(V) bool, seq iter.Seq[V]) bool

AnyFunc returns true if checker returns true for any element in seq, otherwise it returns false.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func isEven(i int) bool { return i%2 == 0 }
func isOdd(i int) bool  { return i%2 == 1 }

func main() {
	evenAndOdd := []int{1, 2, 3, 4, 5}
	onlyOdd := []int{1, 3, 5, 7}
	onlyEven := []int{2, 4, 6, 8}

	fmt.Println(itertools.AnyFunc(isEven, slices.Values(evenAndOdd)))
	fmt.Println(itertools.AnyFunc(isEven, slices.Values(onlyOdd)))
	fmt.Println(itertools.AnyFunc(isEven, slices.Values(onlyEven)))

	fmt.Println(itertools.AnyFunc(isOdd, slices.Values(evenAndOdd)))
	fmt.Println(itertools.AnyFunc(isOdd, slices.Values(onlyOdd)))
	fmt.Println(itertools.AnyFunc(isOdd, slices.Values(onlyEven)))

}
Output:

true
false
true
true
true
false

func AnyFunc2

func AnyFunc2[K comparable, V any](checker func(K, V) bool, seq iter.Seq2[K, V]) bool

AnyFunc2 returns true if checker returns true for any element in seq otherwise it returns false.

Example
package main

import (
	"fmt"
	"maps"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	m := map[string]int{"foo": 1, "bar": 2, "buz": 3, "bux": 4}

	fmt.Println(itertools.AnyFunc2(func(k string, _ int) bool { return k[0] == 'b' }, maps.All(m)))
	fmt.Println(itertools.AnyFunc2(func(k string, _ int) bool { return k[0] == 'z' }, maps.All(m)))
	fmt.Println(itertools.AnyFunc2(func(_ string, i int) bool { return i > 10 }, maps.All(m)))
	fmt.Println(
		itertools.AnyFunc2(func(k string, i int) bool { return k == "foo" && i == 1 }, maps.All(m)),
	)

}
Output:

true
false
false
true

func Chain

func Chain[V any](seqs ...iter.Seq[V]) iter.Seq[V]

Chain returns a iter.Seq that returns elements from the first sequence until it is exhausted, then proceeds to the next sequence, until all sequences are exhausted.

Example
package main

import (
	"fmt"
	"iter"
	"slices"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	seqs := []iter.Seq[int]{
		slices.Values([]int{1, 2, 3}),
		slices.Values([]int{4, 5, 6}),
	}

	for n := range itertools.Chain(seqs...) {
		fmt.Println(n)
	}

}
Output:

1
2
3
4
5
6

func Chain2

func Chain2[K comparable, V any](iters ...iter.Seq2[K, V]) iter.Seq2[K, V]

Chain2 returns a iter.Seq2 similar to Chain, returning a iter.Seq2 that runs over all the provider iterators.

Example
package main

import (
	"fmt"
	"iter"
	"maps"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	seqs := []iter.Seq2[string, int]{
		maps.All(map[string]int{"foo": 1, "bar": 2}),
		maps.All(map[string]int{"baz": 3, "wat": 4}),
	}

	res := itertools.Chain2(seqs...)
	for k, v := range res {
		fmt.Println(k, v)
	}

}
Output:

foo 1
bar 2
baz 3
wat 4

func ChainMaps added in v0.4.0

func ChainMaps[K comparable, V any](mps ...map[K]V) iter.Seq2[K, V]

ChainMaps is like Chain but for maps.

Example
package main

import (
	"fmt"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	map1 := map[string]int{"foo": 1, "bar": 2}
	map2 := map[string]int{"baz": 3, "wat": 4}

	res := itertools.ChainMaps(map1, map2)

	for k, v := range res {
		fmt.Println(k, v)
	}

}
Output:

foo 1
bar 2
baz 3
wat 4

func ChainSlices added in v0.4.0

func ChainSlices[V any](sls ...[]V) iter.Seq[V]

ChainSlices is a convenience method for calling Chain given slices.

E.g instead of something like:

var res []V
res = append(res, firstSlice...)
res = append(res, secondSlie...)
// more slices ...

for _, v := range res {
	// do stuff with v ...
}

You can call:

for v := range ChainSlices(firstSlice, secondSlice, /* more slices ... */) {
	// do stuff with v ...
}
Example
package main

import (
	"fmt"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	slice1 := []int{1, 2, 3}
	slice2 := []int{11, 12, 13}

	seq := itertools.ChainSlices(slice1, slice2)

	for n := range seq {
		fmt.Println(n)
	}

}
Output:

1
2
3
11
12
13

func CollectIntoMap

func CollectIntoMap[K comparable, V any](seq iter.Seq2[K, V], dest map[K]V)

CollectIntoMap is like maps.Collect but accepts a pre-allocated map to collect values into.

Example
package main

import (
	"fmt"
	"maps"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	data := map[string]int{"foo": 1, "bar": 2}
	mapper := func(k string, x int) (string, int) { return k + "_new", x + 2 }
	dest := make(map[string]int, len(data))

	itertools.CollectIntoMap(itertools.Map2(mapper, maps.All(data)), dest)

	for k, v := range dest {
		fmt.Println(k, v)
	}

}
Output:

foo_new 3
bar_new 4
Example (ConcatMaps)
package main

import (
	"fmt"
	"maps"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	map1 := map[string]int{"A": 1, "B": 2, "C": 3}
	map2 := map[string]int{"D": 4, "E": 5, "F": 6}
	dest := make(map[string]int, len(map1)+len(map2))

	itertools.CollectIntoMap(itertools.Chain2(maps.All(map1), maps.All(map2)), dest)

	for k, v := range dest {
		fmt.Println(k, v)
	}

}
Output:

A 1
B 2
C 3
D 4
E 5
F 6

func CollectIntoSlice

func CollectIntoSlice[V any](seq iter.Seq[V], dest []V)

CollectIntoSlice is like slices.Collect but accepts a pre-allocated slice to collect values into.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	data := []int{1, 2, 3, 4}
	mapper := func(x int) int { return 2 * x }
	dest := make([]int, len(data))

	itertools.CollectIntoSlice(itertools.Map(mapper, slices.Values(data)), dest)

	for _, n := range dest {
		fmt.Println(n)
	}

}
Output:

2
4
6
8

func Compress

func Compress[V any](seq iter.Seq[V], selectors iter.Seq[bool]) iter.Seq[V]

Compress returns a iter.Seq that returns elements from seq where the corresponding element in selectors is true. Stops when either the data or selectors iterables have been exhausted.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	seq := slices.Values([]string{"A", "B", "C", "D", "E"})
	selectors := slices.Values([]bool{true, true, false, true, false})

	for s := range itertools.Compress(seq, selectors) {
		fmt.Println(s)
	}

}
Output:

A
B
D

func Compress2

func Compress2[K comparable, V any](seq iter.Seq2[K, V], selectors iter.Seq[bool]) iter.Seq2[K, V]

Compress2 is like Compress but for iter.Seq2.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	seq := slices.All([]int{1, 2, 3, 4, 5})
	selectors := slices.Values([]bool{true, false, false, true, true})

	for x1, x2 := range itertools.Compress2(seq, selectors) {
		fmt.Println(x1, x2)
	}

}
Output:

0 1
3 4
4 5

func Cycle

func Cycle[V any](iterable iter.Seq[V]) iter.Seq[V]

Cycle returns a iter.Seq that returns elements from the iterable and saves a copy of each. When the iterable is exhausted, elements from the saved copy are returned. Repeats indefinitely.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	res := itertools.Cycle(slices.Values([]string{"A", "B", "C", "D"}))

	for i, s := range itertools.Enumerate(res, 1) {
		fmt.Println(s)
		if i == 12 {
			break
		}
	}

}
Output:

A
B
C
D
A
B
C
D
A
B
C
D

func Cycle2

func Cycle2[K comparable, V any](iterable iter.Seq2[K, V]) iter.Seq2[K, V]
Example
package main

import (
	"fmt"
	"maps"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	itemsSeq := itertools.Cycle2(
		maps.All(map[string]int{"one": 1, "two": 2, "three": 3, "four": 4}),
	)

	for k, v := range itertools.SliceUntil2(itemsSeq, 8, 1) {
		fmt.Println(k, v)
	}

}
Output:

one 1
two 2
three 3
four 4
one 1
two 2
three 3
four 4

func DropWhile

func DropWhile[V any](seq iter.Seq[V], predicate func(V) bool) iter.Seq[V]

DropWhile returns a iter.Seq that drops elements from seq while the predicate is true and afterwards returns every element.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	seq := slices.Values([]int{1, 4, 6, 3, 8})
	predicate := func(i int) bool { return i < 5 }

	for n := range itertools.DropWhile(seq, predicate) {
		fmt.Println(n)
	}

}
Output:

6
3
8

func DropWhile2

func DropWhile2[K comparable, V any](
	seq iter.Seq2[K, V],
	predicate func(K, V) bool,
) iter.Seq2[K, V]

DropWhile2 is like DropWhile but for iter.Seq2.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	seq := slices.All([]int{1, 4, 6, 11, 8})
	predicate := func(i int, n int) bool { return n < 5 || i < 3 }

	for i, n := range itertools.DropWhile2(seq, predicate) {
		fmt.Println(i, n)
	}

}
Output:

3 11
4 8

func Enumerate

func Enumerate[V any](seq iter.Seq[V], start int) iter.Seq2[int, V]

Enumerate returns a iter.Seq2 which yields a count, starting from start, and the values obtained from iterating over seq.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	seq := itertools.Chain(
		slices.Values([]int{10, 11, 12, 13}),
		slices.Values([]int{14, 15, 16, 17}),
	)

	res := itertools.Enumerate(seq, 2)

	for i, n := range res {
		fmt.Println(i, n)
	}

}
Output:

2 10
3 11
4 12
5 13
6 14
7 15
8 16
9 17

func Filter

func Filter[V any](filterFunc func(V) bool, seq iter.Seq[V]) iter.Seq[V]

Filter returns a iter.Seq from those elements of seq for which filterFunc is true.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	seq := slices.Values([]int{1, 2, 3, 4, 5})

	res := itertools.Filter(func(i int) bool { return i%2 == 1 }, seq)

	for n := range res {
		fmt.Println(n)
	}

}
Output:

1
3
5

func Filter2

func Filter2[K comparable, V any](filterFunc func(K, V) bool, seq iter.Seq2[K, V]) iter.Seq2[K, V]

Filter2 returns a iter.Seq2 similar to Filter.

Example
package main

import (
	"fmt"
	"maps"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	seq := maps.All(
		map[string]int{"foo": 1, "bar": 2, "buz": 3, "baz": 4, "bux": 5},
	)

	res := itertools.Filter2(
		func(k string, v int) bool {
			return k[0] == 'b' && v%2 == 0
		},
		seq,
	)

	for k, v := range res {
		fmt.Println(k, v)
	}

}
Output:

bar 2
baz 4

func FirstFunc added in v0.3.0

func FirstFunc[V any](checker func(V) bool, seq iter.Seq[V]) (V, bool)

FirstFunc returns the first value in seq for which checker returns true and 'true' or the zero value for type V and 'false' if no element of seq satisfiers checker.

Example
package main

import (
	"fmt"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	nums := itertools.RangeUntil(5, 1)

	x, found := itertools.FirstFunc(func(x int) bool { return x > 1 }, nums)
	fmt.Println(x, found)

	x, found = itertools.FirstFunc(func(x int) bool { return x > 10 }, nums)
	fmt.Println(x, found)

}
Output:

2 true
0 false

func FirstFunc2 added in v0.3.0

func FirstFunc2[K comparable, V any](
	checker func(K, V) bool,
	seq iter.Seq2[K, V],
) (K, V, bool)

FirstFunc2 returns the first pair of values in seq for which checker returns true and 'true' or the zero values for types K and V and 'false' if no element of seq satisfiers the checker.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	seq := itertools.ZipPair(
		slices.Values([]string{"one", "two", "three", "four"}),
		slices.Values([]int{1, 2, 3, 4}),
	)

	s, x, found := itertools.FirstFunc2(func(s string, _ int) bool { return s == "one" }, seq)
	fmt.Println(s, x, found)

	s, x, found = itertools.FirstFunc2(func(_ string, x int) bool { return x > 2 }, seq)
	fmt.Println(s, x, found)

	s, x, found = itertools.FirstFunc2(
		func(s string, x int) bool { return s == "four" && x > 2 },
		seq,
	)
	fmt.Println(s, x, found)

	s, x, found = itertools.FirstFunc2(
		func(s string, x int) bool { return s != "one" && x < 0 },
		seq,
	)
	fmt.Println(s, x, found)

}
Output:

one 1 true
three 3 true
four 4 true
 0 false

func Flatten added in v0.5.0

func Flatten[K comparable](seq iter.Seq2[K, K]) iter.Seq[K]

Flatten returns a sequence that iterates across all keys and then all values of seq.

Example
package main

import (
	"fmt"
	"maps"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	seq := maps.All(map[string]string{"hello": "world", "goodbye": "all"})

	for n := range itertools.Flatten(seq) {
		fmt.Println(n)
	}

}
Output:

hello
world
goodbye
all

func FlattenMap added in v0.5.0

func FlattenMap[K comparable](m map[K]K) iter.Seq[K]

FlattenMap is a convenience wrapper of Flatten.

Example
package main

import (
	"fmt"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	m := map[string]string{"hello": "world", "goodbye": "all"}

	for n := range itertools.FlattenMap(m) {
		fmt.Println(n)
	}

}
Output:

hello
world
goodbye
all

func IterCtx

func IterCtx[V any](ctx context.Context, seq iter.Seq[V]) iter.Seq[V]

IterCtx returns a iter.Seq that yields values from seq until either seq is exhausted or ctx is cancelled, whichever comes first.

Example
package main

import (
	"context"
	"fmt"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	seq := itertools.Repeat("iterating", -1)
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	count := 0
	for c := range itertools.IterCtx(ctx, seq) {
		if count == 5 {
			cancel()
		}
		fmt.Println(c)
		count++
	}

}
Output:

iterating
iterating
iterating
iterating
iterating
iterating

func IterCtx2

func IterCtx2[K comparable, V any](ctx context.Context, seq iter.Seq2[K, V]) iter.Seq2[K, V]

IterCtx2 is like IterCtx but for iter.Seq2 sequences.

Example
package main

import (
	"context"
	"fmt"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	seq := itertools.Enumerate(itertools.Repeat("iterating", -1), 1)
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	for i, c := range itertools.IterCtx2(ctx, seq) {
		if i == 4 {
			cancel()
		}
		fmt.Println(i, c)
	}

}
Output:

1 iterating
2 iterating
3 iterating
4 iterating

func Keys

func Keys[K comparable, V any](seq iter.Seq2[K, V]) iter.Seq[K]

Keys returns a iter.Seq over the keys of seq.

func Map

func Map[V1 any, V2 any](mapFunc func(V1) V2, seq iter.Seq[V1]) iter.Seq[V2]

Map returns a iter.Seq that applies mapFunc to every item of iterable, yielding the results.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	seq := slices.Values([]int{1, 2, 3})

	res := itertools.Map(func(i int) int { return i * 2 }, seq)

	for n := range res {
		fmt.Println(n)
	}

}
Output:

2
4
6

func Map2

func Map2[K1 comparable, V1 any, K2 comparable, V2 any](
	mapFunc func(K1, V1) (K2, V2),
	seq iter.Seq2[K1, V1],
) iter.Seq2[K2, V2]

Map2 returns a iter.Seq2 similar to Map.

Example
package main

import (
	"fmt"
	"maps"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	seq := maps.All(
		map[string]int{"foo": 1, "bar": 2, "baz": 3},
	)

	res := itertools.Map2(
		func(k string, v int) (string, float64) {
			return k + " halved", float64(v) / 2.0
		},
		seq,
	)

	for k, v := range res {
		fmt.Println(k, v)
	}

}
Output:

foo halved 0.5
bar halved 1
baz halved 1.5

func Max added in v0.5.0

func Max[V cmp.Ordered](seq iter.Seq[V]) V

Max returns the maximal value in seq. It panics if seq is empty. For floating-point V, Max propagates NaNs (any NaN value in seq forces the output to be NaN).

Example
package main

import (
	"fmt"
	"slices"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	seq := slices.Values([]int{1, 11, -1, 4, 5})

	fmt.Println(itertools.Max(seq))

}
Output:

11
Example (WithNaN)
package main

import (
	"fmt"
	"math"
	"slices"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	seq := slices.Values([]float64{1.0, math.NaN(), 2.0})

	fmt.Println(itertools.Max(seq))

}
Output:

NaN

func MaxFunc added in v0.5.0

func MaxFunc[V any](seq iter.Seq[V], cmp func(a V, b V) int) V

MaxFunc returns the maximal value in seq, using cmp to compare elements. It panics if seq is empty. If there is more than one maximal element according to the cmp function, MaxFunc returns the first one. cmp should return values like cmp.Compare.

Example
package main

import (
	"fmt"
	"slices"
	"strings"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	seq := slices.Values([]string{"bar", "foo", "abc"})

	fmt.Printf("%+v\n", itertools.MaxFunc(seq, strings.Compare))

}
Output:

foo

func Min added in v0.5.0

func Min[V cmp.Ordered](seq iter.Seq[V]) V

Min returns the minimal value in seq. It panics if seq is empty. For floating-point V, Min propagates NaNs (any NaN value in seq forces the output to be NaN).

Example
package main

import (
	"fmt"
	"slices"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	seq := slices.Values([]int{1, 11, -1, 4, 5})

	fmt.Println(itertools.Min(seq))

}
Output:

-1
Example (WithNaN)
package main

import (
	"fmt"
	"math"
	"slices"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	seq := slices.Values([]float64{1.0, math.NaN(), 2.0})

	fmt.Println(itertools.Min(seq))

}
Output:

NaN

func MinFunc added in v0.5.0

func MinFunc[V any](seq iter.Seq[V], cmp func(a V, b V) int) V

MinFunc returns the maximal value in seq, using cmp to compare elements. It panics if seq is empty. If there is more than one maximal element according to the cmp function, MinFunc returns the first one. cmp should return values like cmp.Compare.

Example
package main

import (
	"fmt"
	"slices"
	"strings"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	seq := slices.Values([]string{"foo", "bar", "abc"})

	fmt.Printf("%+v\n", itertools.MinFunc(seq, strings.Compare))

}
Output:

abc

func Pairwise added in v0.5.0

func Pairwise[V comparable](seq iter.Seq[V]) iter.Seq2[V, V]

Pairwise returns successive overlapping pairs taken from the input sequence. It will be empty if the input iterable has fewer than two values.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	seq := slices.Values([]string{"A", "B", "C", "D", "E", "F", "G"})

	for n, m := range itertools.Pairwise(seq) {
		fmt.Println(n, m)
	}

}
Output:

A B
B C
C D
D E
E F
F G

func Range

func Range(start int, end int, step int) iter.Seq[int]

Range returns a iter.Seq that yields values step distance apart from start until end, not including end.

Range panics if step is 0.

Example
package main

import (
	"fmt"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	for n := range itertools.Range(2, 10, 2) {
		fmt.Println(n)
	}

}
Output:

2
4
6
8

func RangeFrom

func RangeFrom(start int, step int) iter.Seq[int]

Range from is like Range but has no end.

func RangeUntil

func RangeUntil(end int, step int) iter.Seq[int]

RangeUntil is equivalent to

Range(0, end, step)
Example
package main

import (
	"fmt"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	for n := range itertools.RangeUntil(10, 3) {
		fmt.Println(n)
	}

}
Output:

0
3
6
9

func Repeat

func Repeat[V any](value V, times int) iter.Seq[V]

Repeat returns a iter.Seq that returns value over and over again. Runs indefinitely if times is negative, otherwise runs that many times.

Example
package main

import (
	"fmt"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	res := itertools.Repeat("A", 7)

	for s := range res {
		fmt.Println(s)
	}

}
Output:

A
A
A
A
A
A
A

func Slice

func Slice[V any](seq iter.Seq[V], start int, end int, step int) iter.Seq[V]

Slice returns a iter.Seq that slices up the provided sequence: returning elements step distance apart from start until end (excluding end).

If 'end' is negative then the returned sequence will run until 'seq' is exhausted. Slice will panic if step is not a positive integer.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	seq := slices.Values([]string{"A", "B", "C", "D", "E", "F", "G", "H"})

	for s := range itertools.Slice(seq, 1, 9, 2) {
		fmt.Println(s)
	}

}
Output:

B
D
F
H

func Slice2

func Slice2[K comparable, V any](
	seq iter.Seq2[K, V],
	start int,
	end int,
	step int,
) iter.Seq2[K, V]

Slice2 is like Slice but for iter.Seq2.

Like Slice it will panic if step is not a positive integer.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	seq := itertools.ZipPair(
		slices.Values([]int{1, 2, 3, 4, 5}),
		slices.Values([]int{11, 12, 13, 14, 15}),
	)

	for x1, x2 := range itertools.Slice2(seq, 1, 5, 2) {
		fmt.Println(x1, x2)
	}

}
Output:

2 12
4 14

func SliceFrom added in v0.5.0

func SliceFrom[V any](seq iter.Seq[V], start int, step int) iter.Seq[V]

SliceFrom is equivalent to

Slice(seq, start, -1, end)
Example
package main

import (
	"fmt"
	"slices"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	seq := slices.Values([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})

	for s := range itertools.SliceFrom(seq, 0, 3) {
		fmt.Println(s)
	}

}
Output:

1
4
7
10

func SliceFrom2 added in v0.5.0

func SliceFrom2[K comparable, V any](seq iter.Seq2[K, V], start int, step int) iter.Seq2[K, V]

SliceFrom2 is like SliceFrom but for iter.Seq2.

Example
package main

import (
	"fmt"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	seq := itertools.ZipPair(
		itertools.Range(0, 10, 1),
		itertools.Range(1, 11, 1),
	)

	for x1, x2 := range itertools.SliceFrom2(seq, 0, 2) {
		fmt.Println(x1, x2)
	}

}
Output:

0 1
2 3
4 5
6 7
8 9

func SliceUntil

func SliceUntil[V any](seq iter.Seq[V], end int, step int) iter.Seq[V]

SliceUntil is a equivalent to

Slice(seq, 0, end, step)
Example
package main

import (
	"fmt"
	"slices"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	seq := slices.Values([]string{"A", "B", "C", "D", "E", "F", "G", "H"})

	for s := range itertools.SliceUntil(seq, 5, 2) {
		fmt.Println(s)
	}

}
Output:

A
C
E

func SliceUntil2

func SliceUntil2[K comparable, V any](seq iter.Seq2[K, V], end int, step int) iter.Seq2[K, V]

SliceUntil2 is like SliceUntil but for iter.Seq2.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	seq := itertools.ZipPair(
		slices.Values([]int{1, 2, 3, 4, 5}),
		slices.Values([]int{11, 12, 13, 14, 15}),
	)

	for x1, x2 := range itertools.SliceUntil2(seq, 4, 2) {
		fmt.Println(x1, x2)
	}

}
Output:

1 11
3 13

func TakeWhile

func TakeWhile[V any](seq iter.Seq[V], predicate func(V) bool) iter.Seq[V]

TakeWhile returns a iter.Seq that returns elements from seq while the predicate is true.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	seq := slices.Values([]int{1, 4, 6, 3, 8})
	predicate := func(i int) bool { return i < 5 }

	for n := range itertools.TakeWhile(seq, predicate) {
		fmt.Println(n)
	}

}
Output:

1
4

func TakeWhile2

func TakeWhile2[K comparable, V any](
	seq iter.Seq2[K, V],
	predicate func(K, V) bool,
) iter.Seq2[K, V]

TakeWhile2 is like TakeWhile2 but for iter.Seq2.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	seq := slices.All([]int{1, 4, 6, 3, 8})
	predicate := func(i int, n int) bool { return n < 5 && i <= 2 }

	for i, n := range itertools.TakeWhile2(seq, predicate) {
		fmt.Println(i, n)
	}

}
Output:

0 1
1 4

func Values

func Values[K comparable, V any](seq iter.Seq2[K, V]) iter.Seq[V]

Values returns a iter.Seq over the values of seq.

func Zip

func Zip[V any](seqs ...iter.Seq[V]) iter.Seq[V]

Zip returns a iter.Seq the iterates over each sequence in seqs in parallel. Stops when the shortest sequence is exhausted.

Example
package main

import (
	"fmt"
	"iter"
	"slices"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	seqs := []iter.Seq[int]{
		slices.Values([]int{1, 2, 3}),
		slices.Values([]int{11, 12, 13}),
	}

	res := itertools.Zip(seqs...)

	for n := range res {
		fmt.Println(n)
	}

}
Output:

1
11
2
12
3
13

func Zip2

func Zip2[K comparable, V any](seqs ...iter.Seq2[K, V]) iter.Seq2[K, V]

Zip2 returns a iter.Seq2 like Zip.

Example
package main

import (
	"fmt"
	"iter"
	"slices"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	seqs := []iter.Seq2[int, int]{
		slices.All([]int{1, 2, 3}),
		slices.All([]int{11, 12, 13}),
	}

	res := itertools.Zip2(seqs...)

	for i, n := range res {
		fmt.Println(i, n)
	}

}
Output:

0 1
0 11
1 2
1 12
2 3
2 13

func ZipLongest

func ZipLongest[V any](fillValue V, seqs ...iter.Seq[V]) iter.Seq[V]

ZipLongest returns a iter.Seq like Zip but if the sequences are of uneven length, missing values are filled-in with fillValue.

Example
package main

import (
	"fmt"
	"iter"
	"slices"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	seqs := []iter.Seq[int]{
		slices.Values([]int{1, 2, 3, 4, 5, 6}),
		slices.Values([]int{11, 12, 13}),
	}

	res := itertools.ZipLongest(-1, seqs...)

	for n := range res {
		fmt.Println(n)
	}

}
Output:

1
11
2
12
3
13
4
-1
5
-1
6
-1

func ZipPair

func ZipPair[V1 any, V2 any](seq1 iter.Seq[V1], seq2 iter.Seq[V2]) iter.Seq2[V1, V2]

Zip returns a iter.Seq2 that yields pairs of values from seq1 and seq2. Stops when either seq of selectors is exhausted.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/matthewhughes934/go-itertools/itertools"
)

func main() {
	names := slices.Values([]string{"one", "two", "three"})
	values := slices.Values([]int{1, 2, 3})

	for n, v := range itertools.ZipPair(names, values) {
		fmt.Println(n, v)
	}

}
Output:

one 1
two 2
three 3

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL