iterutil

package module
v0.5.1 Latest Latest
Warning

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

Go to latest
Published: Jan 21, 2025 License: MIT Imports: 4 Imported by: 0

README

jub0bs/iterutil

tag Go Version Go Reference license build codecov goreport

An experimental collection of utility functions (sources, combinators, sinks) for working with Go iterators.

Installation

go get github.com/jub0bs/iterutil

jub0bs/iterutil requires Go 1.23.2 or above.

Documentation

The documentation is available on pkg.go.dev.

Code coverage

coverage

License

All source code is covered by the MIT License.

FAQ

What inspired this library?
Can I depend on this library?

You can, but at your own peril. At this early stage, I reserve the right, upon new releases, to break the API: some functions may see their names, signatures, and/or behaviors change, and some functions may be removed altogether.

If you need a few functions from this library but do not want to depend on it, feel free to copy their sources in your project; a little copying is better than a little dependency.

How should I use this library?

Above all, use it with parsimony. Chaining many combinators is far from ideal for several reasons:

  • code readability may suffer, in part because Go's idiosyncracies hinder "fluent chaining" and because Go lacks a concise notation for anonymous functions;
  • a more classic and imperative style is likely to prove more performant;
  • Go lacks the powerful laziness of Haskell.

Bear in mind that the existence of this library is no license to overuse combinator chaining in your codebase!

Documentation

Overview

An experimental collection of utility functions (sources, combinators, and sinks) that complement the iter package.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func At

func At[I constraints.Integer, E any](seq iter.Seq[E], n I) (e E, ok bool)

At, if count is non-negative, returns the element at index n in seq and true or the zero value and false if seq contains fewer than n+1 elements; otherwise, it panics.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/jub0bs/iterutil"
)

func main() {
	seq := slices.Values([]string{"foo", "bar", "baz", "qux"})
	fmt.Println(iterutil.At(seq, 2))
}
Output:

baz true

func Between added in v0.3.0

func Between[I constraints.Signed](n, m, step I) iter.Seq[I]

Between, if step is nonzero, returns an iterator ranging from n (inclusive) to m (exclusive) in increments of step; otherwise, it panics.

Example
package main

import (
	"fmt"

	"github.com/jub0bs/iterutil"
)

func main() {
	for i := range iterutil.Between(2, 9, 3) {
		fmt.Println(i)
	}
}
Output:

2
5
8

func Compare added in v0.3.0

func Compare[E cmp.Ordered](seq1, seq2 iter.Seq[E]) int

Compare compares the elements of seq1 and seq2, using cmp.Compare on each pair of elements. The elements are compared sequentially until one element is not equal to the other. The result of comparing the first non-matching elements is returned. If seq1 and seq2 are equal until one of them ends, the shorter one is considered less than the longer one. The result is 0 if seq1 == seq2, -1 if seq1 < seq2, and +1 if seq1 > seq2. For floating-point types, a NaN is considered less than any non-NaN, and -0.0 is not less than (is equal to) 0.0. It may not terminate if seq1 or seq2 or both are infinite.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/jub0bs/iterutil"
)

func main() {
	seq1 := slices.Values([]string{"foo", "bar", "baz", "qux"})
	seq2 := slices.Values([]string{"foo", "bar", "baz", "qux", "quux"})
	fmt.Println(iterutil.Compare(seq1, seq2))
}
Output:

-1

func CompareFunc added in v0.3.0

func CompareFunc[A, B any](seq1 iter.Seq[A], seq2 iter.Seq[B], cmp func(A, B) int) int

CompareFunc is like Compare but uses a custom comparison function on each pair of elements. The result is the first non-zero result of cmp; if cmp always returns 0, the result is 0 if len(seq1) == len(seq2), -1 if len(seq1) < len(seq2), and +1 if len(seq1) > len(seq2). It may not terminate if seq1 or seq2 or both are infinite.

Example
package main

import (
	"cmp"
	"fmt"
	"slices"

	"github.com/jub0bs/iterutil"
)

func main() {
	seq1 := slices.Values([]string{"foo", "bar", "baz", "qux", "quux"})
	seq2 := slices.Values([]string{"000", "111", "222", "333", "4444"})
	lenCmp := func(s1, s2 string) int { return cmp.Compare(len(s1), len(s2)) }
	fmt.Println(iterutil.CompareFunc(seq1, seq2, lenCmp))
}
Output:

0

func Concat

func Concat[E any](seqs ...iter.Seq[E]) iter.Seq[E]

Concat returns an iterator concatenating the passed in iterators.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/jub0bs/iterutil"
)

func main() {
	seq1 := slices.Values([]string{"foo", "bar"})
	seq2 := slices.Values([]string{"baz", "qux"})
	for s := range iterutil.Concat(seq1, seq2) {
		fmt.Println(s)
	}
}
Output:

foo
bar
baz
qux

func Contains

func Contains[E comparable](seq iter.Seq[E], target E) bool

Contains report whether target is present in seq. It may not terminate if seq is infinite.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/jub0bs/iterutil"
)

func main() {
	seq := slices.Values([]int{1})
	fmt.Println(iterutil.Contains(seq, 2))
	seq = slices.Values([]int{1, 2, 3})
	fmt.Println(iterutil.Contains(seq, 2))
}
Output:

false
true

func ContainsFunc

func ContainsFunc[E any](seq iter.Seq[E], p func(E) bool) bool

ContainsFunc reports whether at least one element e of seq satisfies p(e). It may not terminate if seq is infinite.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/jub0bs/iterutil"
)

func main() {
	isEven := func(i int) bool { return i%2 == 0 }
	seq := slices.Values([]int{1})
	fmt.Println(iterutil.ContainsFunc(seq, isEven))
	seq = slices.Values([]int{1, 2, 3})
	fmt.Println(iterutil.ContainsFunc(seq, isEven))
}
Output:

false
true

func Cycle

func Cycle[E any](seq iter.Seq[E]) iter.Seq[E]

Cycle returns an iterator that infinitely repeats seq.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/jub0bs/iterutil"
)

func main() {
	seq := slices.Values([]int{1, 2, 3})
	var count int
	for i := range iterutil.Cycle(seq) {
		count++
		if count > 5 {
			break
		}
		fmt.Println(i)
	}
}
Output:

1
2
3
1
2

func Drop

func Drop[I constraints.Integer, E any](seq iter.Seq[E], count I) iter.Seq[E]

Drop returns the suffix of seq after the first min(max(count, 0), Len(seq)) elements.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/jub0bs/iterutil"
)

func main() {
	seq := slices.Values([]string{"foo", "bar", "baz", "qux"})
	for s := range iterutil.Drop(seq, 3) {
		fmt.Println(s)
	}
}
Output:

qux

func DropWhile

func DropWhile[E any](seq iter.Seq[E], p func(E) bool) iter.Seq[E]

DropWhile returns the suffix remaining after the longest prefix of seq of elements that satisfy p.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/jub0bs/iterutil"
)

func main() {
	seq := slices.Values([]string{"foo", "bar", "baz", "qux"})
	isNotBaz := func(s string) bool { return s != "baz" }
	for s := range iterutil.DropWhile(seq, isNotBaz) {
		fmt.Println(s)
	}
}
Output:

baz
qux

func Empty

func Empty[E any]() iter.Seq[E]

Empty returns an empty iterator.

Example
package main

import (
	"fmt"

	"github.com/jub0bs/iterutil"
)

func main() {
	for i := range iterutil.Empty[int]() {
		fmt.Println(i)
	}
}
Output:

func Enumerate added in v0.3.0

func Enumerate[I constraints.Integer, E any](seq iter.Seq[E]) iter.Seq2[I, E]

Enumerate returns an iterator over pairs of indices (starting at 0) and elements of seq.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/jub0bs/iterutil"
)

func main() {
	seq := slices.Values([]string{"foo", "bar", "baz"})
	for i, v := range iterutil.Enumerate[int](seq) {
		fmt.Println(i, v)
	}
}
Output:

0 foo
1 bar
2 baz

func Equal added in v0.3.0

func Equal[E comparable](seq1, seq2 iter.Seq[E]) bool

Equal reports whether two iterators are equal: the same length and all elements equal. If the lengths are different, Equal returns false. Otherwise, the elements are compared sequentially, and the comparison stops at the first unequal pair. Floating point NaNs are not considered equal. Equal may not terminate if seq1 or seq2 or both are infinite.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/jub0bs/iterutil"
)

func main() {
	seq1 := slices.Values([]string{"foo", "bar", "baz", "qux"})
	seq2 := slices.Values([]string{"foo", "bar", "baz", "qux"})
	fmt.Println(iterutil.Equal(seq1, seq2))
}
Output:

true

func EqualFunc added in v0.3.0

func EqualFunc[A, B comparable](seq1 iter.Seq[A], seq2 iter.Seq[B], eq func(A, B) bool) bool

EqualFunc reports whether two iterators are equal using eq as equality function on each pair of elements. If the lengths are different, EqualFunc returns false. Otherwise, the elements are compared sequentially, and the comparison stops at the first pair for which eq returns false. EqualFunc may not terminate if seq1 or seq2 or both are infinite.

Example
package main

import (
	"fmt"
	"slices"
	"strings"

	"github.com/jub0bs/iterutil"
)

func main() {
	seq1 := slices.Values([]string{"foo", "bar", "baz", "qux"})
	seq2 := slices.Values([]string{"foO", "bAr", "Baz", "QUX"})
	fmt.Println(iterutil.EqualFunc(seq1, seq2, strings.EqualFold))
}
Output:

true

func Filter

func Filter[E any](seq iter.Seq[E], p func(E) bool) iter.Seq[E]

Filter returns an iterator composed of the elements of seq that satisfy predicate p.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/jub0bs/iterutil"
)

func main() {
	seq := slices.Values([]int{1, 42, 99, 100})
	isOdd := func(i int) bool { return i%2 != 0 }
	for s := range iterutil.Filter(seq, isOdd) {
		fmt.Println(s)
	}
}
Output:

1
99

func Filter2

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

Filter returns an iterator composed of the pairs of seq that satisfy predicate p.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/jub0bs/iterutil"
)

func main() {
	seq := slices.All([]string{"zero", "one", "two", "three", "four"})
	isShort := func(_ int, s string) bool { return len(s) < 5 }
	for i, s := range iterutil.Filter2(seq, isShort) {
		fmt.Println(i, s)
	}
}
Output:

0 zero
1 one
2 two
4 four

func Flatten added in v0.3.0

func Flatten[E any](seqs iter.Seq[iter.Seq[E]]) iter.Seq[E]

Flatten returns an iterator resulting from the concatenation of all iterators in seqs.

Example
package main

import (
	"fmt"
	"iter"
	"slices"

	"github.com/jub0bs/iterutil"
)

func main() {
	seq1 := slices.Values([]string{"foo", "bar"})
	seq2 := slices.Values([]string{"baz", "qux"})
	seqs := slices.Values([]iter.Seq[string]{seq1, seq2})
	for s := range iterutil.Flatten(seqs) {
		fmt.Println(s)
	}
}
Output:

foo
bar
baz
qux

func IsEmpty

func IsEmpty[E any](seq iter.Seq[E]) bool

IsEmpty reports whether seq is an empty iterator.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/jub0bs/iterutil"
)

func main() {
	seq := slices.Values([]int{})
	fmt.Println(iterutil.IsEmpty(seq))
	seq = slices.Values([]int{1, 2, 3, 4})
	fmt.Println(iterutil.IsEmpty(seq))
}
Output:

true
false

func IsSorted added in v0.3.0

func IsSorted[E cmp.Ordered](seq iter.Seq[E]) bool

IsSorted reports whether seq is sorted in ascending order. For floating-point types, a NaN is considered less than any non-NaN, and -0.0 is not less than (is equal to) 0.0. It may not terminate if seq is infinite.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/jub0bs/iterutil"
)

func main() {
	seq := slices.Values([]string{"bar", "baz", "foo", "quux", "qux"})
	fmt.Println(iterutil.IsSorted(seq))
}
Output:

true

func IsSortedFunc added in v0.3.0

func IsSortedFunc[E any](seq iter.Seq[E], cmp func(E, E) int) bool

IsSortedFunc reports whether seq is sorted in ascending order, using cmp as comparison function. It may not terminate if seq is infinite.

Example
package main

import (
	"cmp"
	"fmt"
	"slices"

	"github.com/jub0bs/iterutil"
)

func main() {
	seq := slices.Values([]string{"bar", "baz", "foo", "qux", "quux"})
	lenCmp := func(s1, s2 string) int { return cmp.Compare(len(s1), len(s2)) }
	fmt.Println(iterutil.IsSortedFunc(seq, lenCmp))
}
Output:

true

func Iterate

func Iterate[E any](e E, f func(E) E) iter.Seq[E]

Iterate returns an infinite iterator composed of repeated applications of f to e.

Example
package main

import (
	"fmt"

	"github.com/jub0bs/iterutil"
)

func main() {
	double := func(i int) int { return i + i }
	for i := range iterutil.Iterate(1, double) {
		if i > 20 {
			break
		}
		fmt.Println(i)
	}
}
Output:

1
2
4
8
16

func Left

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

Left return an iterator composed of the keys of the pairs in seq.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/jub0bs/iterutil"
)

func main() {
	seq := slices.All([]string{"zero", "one", "two", "three", "four"})
	for i := range iterutil.Left(seq) {
		fmt.Println(i)
	}
}
Output:

0
1
2
3
4

func Len

func Len[E any](seq iter.Seq[E]) int

Len returns the number of elements in seq. It terminates if and only if seq is finite.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/jub0bs/iterutil"
)

func main() {
	seq := slices.Values([]int{})
	fmt.Println(iterutil.Len(seq))
	seq = slices.Values([]int{1, 2, 3, 4})
	fmt.Println(iterutil.Len(seq))
}
Output:

0
4

func Len2

func Len2[K, V any](seq iter.Seq2[K, V]) int

Len2 returns the number of elements in seq. It terminates if and only if seq is finite.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/jub0bs/iterutil"
)

func main() {
	seq := slices.All([]int(nil))
	fmt.Println(iterutil.Len2(seq))
	seq = slices.All([]int{1, 2, 3, 4})
	fmt.Println(iterutil.Len2(seq))
}
Output:

0
4

func Map

func Map[A, B any](seq iter.Seq[A], f func(A) B) iter.Seq[B]

Map returns the result of applying f to each element of seq.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/jub0bs/iterutil"
)

func main() {
	seq := slices.Values([]string{"one", "two", "three"})
	length := func(s string) int { return len(s) }
	for s := range iterutil.Map(seq, length) {
		fmt.Println(s)
	}
}
Output:

3
3
5

func Max added in v0.3.0

func Max[E cmp.Ordered](seq iter.Seq[E]) (E, bool)

Max, if seq is not empty, returns the maximal value in seq and true; otherwise, it returns the zero value and false. For floating-point numbers, Max propagates NaNs (any NaN value in seq forces the output to be NaN). Max terminates if and only if seq is finite.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/jub0bs/iterutil"
)

func main() {
	seq := slices.Values([]int(nil))
	fmt.Println(iterutil.Max(seq))
	seq = slices.Values([]int{3, 5, 1, 42})
	fmt.Println(iterutil.Max(seq))
}
Output:

0 false
42 true

func MaxFunc added in v0.3.0

func MaxFunc[E any](seq iter.Seq[E], cmp func(E, E) int) (E, bool)

MaxFunc, if seq is not empty, returns the maximal value (using cmp as comparison function) in seq and true; otherwise, it returns the zero value and false. If there is more than one maximal element according to the cmp function, MaxFunc returns the first one. MaxFunc terminates if and only if seq is finite.

Example
package main

import (
	"cmp"
	"fmt"
	"slices"

	"github.com/jub0bs/iterutil"
)

func main() {
	lenCmp := func(s1, s2 string) int { return cmp.Compare(len(s1), len(s2)) }
	seq := slices.Values([]string(nil))
	fmt.Println(iterutil.MaxFunc(seq, lenCmp))
	seq = slices.Values([]string{"qux", "quux", "corge", "grault", "garply"})
	fmt.Println(iterutil.MaxFunc(seq, lenCmp))
}
Output:

 false
grault true

func Min added in v0.3.0

func Min[E cmp.Ordered](seq iter.Seq[E]) (E, bool)

Min, if seq is not empty, returns the minimal value in seq and true; otherwise, it returns the zero value and false. For floating-point numbers, Min propagates NaNs (any NaN value in seq forces the output to be NaN). Min terminates if and only if seq is finite.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/jub0bs/iterutil"
)

func main() {
	seq := slices.Values([]int(nil))
	fmt.Println(iterutil.Min(seq))
	seq = slices.Values([]int{3, 5, 1, 42})
	fmt.Println(iterutil.Min(seq))
}
Output:

0 false
1 true

func MinFunc added in v0.3.0

func MinFunc[E any](seq iter.Seq[E], cmp func(E, E) int) (E, bool)

MinFunc, if seq is not empty, returns the minimal value (using cmp as comparison function) in seq and true; otherwise, it returns the zero value and false. If there is more than one minimal element according to the cmp function, MinFunc returns the first one. MinFunc terminates if and only if seq is finite.

Example
package main

import (
	"cmp"
	"fmt"
	"slices"

	"github.com/jub0bs/iterutil"
)

func main() {
	lenCmp := func(s1, s2 string) int { return cmp.Compare(len(s1), len(s2)) }
	seq := slices.Values([]string(nil))
	fmt.Println(iterutil.MinFunc(seq, lenCmp))
	seq = slices.Values([]string{"quux", "qux", "baz", "bar", "foo"})
	fmt.Println(iterutil.MinFunc(seq, lenCmp))
}
Output:

 false
qux true

func Push

func Push[E any](next func() (E, bool), stop func()) iter.Seq[E]

Push converts the “pull-style” iterator accessed by the two functions next and stop into a “push-style” iterator sequence. Push essentially is the inverse of iter.Pull. Note that you must consume the resulting iterator; otherwise, the underlying pull-based iterator may leak.

Example
package main

import (
	"fmt"
	"iter"
	"slices"

	"github.com/jub0bs/iterutil"
)

func main() {
	seq := slices.Values([]int{1, 2, 3})
	next, stop := iter.Pull(seq)
	for i := range iterutil.Push(next, stop) {
		fmt.Println(i)
	}
}
Output:

1
2
3

func Push2

func Push2[K, V any](next func() (K, V, bool), stop func()) iter.Seq2[K, V]

Push2 converts the “pull-style” iterator accessed by the two functions next and stop into a “push-style” iterator sequence. Push2 essentially is the inverse of iter.Pull2. Note that you must consume the resulting iterator; otherwise, the underlying pull-based iterator may leak.

Example
package main

import (
	"fmt"
	"iter"
	"slices"

	"github.com/jub0bs/iterutil"
)

func main() {
	seq := slices.All([]string{"foo", "bar", "baz"})
	next, stop := iter.Pull2(seq)
	for i, s := range iterutil.Push2(next, stop) {
		fmt.Println(i, s)
	}
}
Output:

0 foo
1 bar
2 baz

func Reduce added in v0.4.0

func Reduce[A, B any](seq iter.Seq[A], b B, f func(B, A) B) B

Reduce performs a left-associative fold of seq using b as the initial value and f as the left-associative binary operation. It terminates if and only if seq is finite.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/jub0bs/iterutil"
)

func main() {
	seq := slices.Values([]int{1, 2, 3, 4, 5, 6})
	plus := func(i, j int) int { return i + j }
	sum := iterutil.Reduce(seq, 0, plus)
	fmt.Println(sum)
}
Output:

21

func Repeat

func Repeat[I constraints.Integer, E any](e E, count I) iter.Seq[E]

Repeat returns an iterator whose values are invariably e. The resulting iterator, if count is non-negative, is of length count; otherwise, it's infinite.

Example
package main

import (
	"fmt"

	"github.com/jub0bs/iterutil"
)

func main() {
	var count int
	for s := range iterutil.Repeat("foo", -1) {
		count++
		if count > 3 {
			break
		}
		fmt.Println(s)
	}
}
Output:

foo
foo
foo
func Right[K, V any](seq iter.Seq2[K, V]) iter.Seq[V]

Right return an iterator composed of the values of the pairs in seq.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/jub0bs/iterutil"
)

func main() {
	seq := slices.All([]string{"zero", "one", "two", "three", "four"})
	for s := range iterutil.Right(seq) {
		fmt.Println(s)
	}
}
Output:

zero
one
two
three
four

func SeqOf

func SeqOf[E any](elems ...E) iter.Seq[E]

SeqOf returns an iterator composed of elems.

Example
package main

import (
	"fmt"

	"github.com/jub0bs/iterutil"
)

func main() {
	for i := range iterutil.SeqOf(1, 2, 3) {
		fmt.Println(i)
	}
}
Output:

1
2
3

func SortedFromMap added in v0.3.0

func SortedFromMap[M ~map[K]V, K cmp.Ordered, V any](m M) iter.Seq2[K, V]

SortedFromMap returns an iterator over the key-value pairs in m ordered by its keys.

Example
package main

import (
	"fmt"

	"github.com/jub0bs/iterutil"
)

func main() {
	m := map[string]int{
		"one":   1,
		"two":   2,
		"three": 3,
	}
	for k, v := range iterutil.SortedFromMap(m) {
		fmt.Println(k, v)
	}
}
Output:

one 1
three 3
two 2

func SortedFromMapFunc added in v0.5.0

func SortedFromMapFunc[M ~map[K]V, K comparable, V any](m M, cmp func(K, K) int) iter.Seq2[K, V]

SortedFromMapFunc returns an iterator over the key-value pairs in m ordered by its keys, using cmp as comparison function.

Note that, for a deterministic behavior, cmp must define a total order on K; for more details, see the testable example labeled "incorrect".

Example
package main

import (
	"fmt"
	"strings"

	"github.com/jub0bs/iterutil"
)

func main() {
	m := map[string]int{
		"one":   1,
		"two":   2,
		"three": 3,
	}
	for k, v := range iterutil.SortedFromMapFunc(m, strings.Compare) {
		fmt.Println(k, v)
	}
}
Output:

one 1
three 3
two 2
Example (Incorrect)
package main

import (
	"cmp"
	"fmt"

	"github.com/jub0bs/iterutil"
)

func main() {
	m := map[string]int{
		"one":   1,
		"two":   2,
		"three": 3,
	}
	lenCmp := func(s1, s2 string) int { return cmp.Compare(len(s1), len(s2)) }
	// Note that lenCmp does not correspond to a total order on strings.
	// More specifically, lenCmp is not antisymmetric:
	// for example, lenCmp("one", "two") = 0 and lenCmp("two", "one") = 0,
	// but "one" != "two".
	for k, v := range iterutil.SortedFromMapFunc(m, lenCmp) {
		fmt.Println(k, v)
	}
	// Consequently, the output is nondeterministic; it may be either
	//
	// one 1
	// two 2
	// three 3
	//
	// or
	//
	// two 2
	// one 1
	// three 3
}
Output:

func Swap

func Swap[K, V any](seq iter.Seq2[K, V]) iter.Seq2[V, K]

Swap returns an iterator over the value-key pairs of seq.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/jub0bs/iterutil"
)

func main() {
	seq := slices.All([]string{"foo", "bar", "baz"})
	for s, i := range iterutil.Swap(seq) {
		fmt.Println(s, i)
	}
}
Output:

foo 0
bar 1
baz 2

func Take

func Take[I constraints.Integer, E any](seq iter.Seq[E], count I) iter.Seq[E]

Take returns the prefix of seq whose length is min(max(count, 0), Len(seq)).

Example
package main

import (
	"fmt"
	"slices"

	"github.com/jub0bs/iterutil"
)

func main() {
	seq := slices.Values([]string{"foo", "bar", "baz", "qux"})
	for s := range iterutil.Take(seq, 2) {
		fmt.Println(s)
	}
}
Output:

foo
bar

func TakeWhile

func TakeWhile[E any](seq iter.Seq[E], p func(E) bool) iter.Seq[E]

TakeWhile returns the longest prefix of seq of elements that satisfy p.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/jub0bs/iterutil"
)

func main() {
	seq := slices.Values([]string{"foo", "bar", "baz", "qux"})
	isNotBaz := func(s string) bool { return s != "baz" }
	for s := range iterutil.TakeWhile(seq, isNotBaz) {
		fmt.Println(s)
	}
}
Output:

foo
bar

func Zip

func Zip[K, V any](seq1 iter.Seq[K], seq2 iter.Seq[V]) iter.Seq2[K, V]

Zip zips seq1 and seq2 into a sequence of corresponding pairs.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/jub0bs/iterutil"
)

func main() {
	french := slices.Values([]string{"un", "deux", "trois", "quatre", "cinq"})
	english := slices.Values([]string{"one", "two", "three"})
	seq := iterutil.Zip(french, english)
	for f, e := range seq {
		fmt.Println(f, "=>", e)
	}
}
Output:

un => one
deux => two
trois => three

func ZipWith

func ZipWith[A, B, C any](seq1 iter.Seq[A], seq2 iter.Seq[B], f func(A, B) C) iter.Seq[C]

ZipWith zips seq1 and seq2 with function f.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/jub0bs/iterutil"
)

func main() {
	french := slices.Values([]string{"un", "deux", "trois", "quatre", "cinq"})
	english := slices.Values([]string{"one", "two", "three", "four"})
	join := func(fr, en string) string { return fr + " => " + en }
	seq := iterutil.ZipWith(french, english, join)
	for s := range seq {
		fmt.Println(s)
	}
}
Output:

un => one
deux => two
trois => three
quatre => four

Types

This section is empty.

Directories

Path Synopsis
Package internal contains two implementations of a binary heap, both of which draw heavy inspiration from package container/heap.
Package internal contains two implementations of a binary heap, both of which draw heavy inspiration from package container/heap.

Jump to

Keyboard shortcuts

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