iter

package
v0.0.0-...-11eb462 Latest Latest
Warning

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

Go to latest
Published: Mar 5, 2023 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

iter is a package for operating on arbitrary collections of elements.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AggregateBy

func AggregateBy[K comparable, V any](i Iterator[V], key func(V) K) map[K][]V

AggregateBy collects elements from an iterable, and groups them by the `key` function.

Similar to GroupBy, except that this function does work like SQL's GROUP BY construct and therefore does not care whether the elements are sorted by the key.

names := ["Alice" "Andrew" "Bob" "Casey" "Adam" "Amelia" "Chloe" "Craig" "Brian"]
AggregateBy(names, name => name[0])
→ map["A":["Alice" "Andrew" "Adam" "Amelia"] "B":["Bob" "Brian"] "C":["Casey" "Chloe" "Craig"]]

func All

func All(i Iterator[bool]) bool

All returns true if all elements from the iterator are true.

All([false true false]) → false
All([false false]) → false
All([true true]) → true
All([]) → true

See functions Any and None; or AllFunc which accepts objects of arbitrary type.

This function short-circuits and may not exhaust the provided iterator.

func AllFunc

func AllFunc[T any](i Iterator[T], f func(T) bool) bool

All returns true if all for all elements `f(elem)` returns true.

type Person struct { Name string; Age int }
AllFunc([Person{"Alice", 30} Person{"Bob", 16}], p => p.Age >= 18) → false
AllFunc([Person{"Bob", 16} Person{"Charlie", 17}], p => p.Age >= 18) → false
AllFunc([Person{"Alice", 30} Person{"Deborah", 47]), p => p.Age >= 18 → true
AllFunc([], p => p.Age >= 18) → true

See functions AnyFunc and NoneFunc; or Any which accepts iterators over booleans.

This function short-circuits and may not exhaust the provided iterator.

func Any

func Any(i Iterator[bool]) bool

Any returns true if any element for the iterator is true.

Any([false true false]) → true
Any([false false]) → false
Any([true true]) → true
Any([]) → false

See functions All and None; or AnyFunc which accepts objects of arbitrary type.

This function short-circuits and may not exhaust the provided iterator.

func AnyFunc

func AnyFunc[T any](i Iterator[T], f func(T) bool) bool

AnyFunc returns true if there's at least one element for which `f(elem)“ is true.

type Person struct { Name string; Age int }
AnyFunc([Person{"Alice", 30} Person{"Bob", 16}], p => p.Age >= 18) → true
AnyFunc([Person{"Bob", 16} Person{"Charlie", 17}], p => p.Age >= 18) → false
AnyFunc([Person{"Alice", 30} Person{"Deborah", 47]), p => p.Age >= 18 → true
AnyFunc([], p => p.Age >= 18) → false

See functions AllFunc and NoneFunc; or Any which accepts iterators over booleans.

This function short-circuits and may not exhaust the provided iterator.

func Count

func Count[T any](i Iterator[T]) int

Count exhausts the iterator and returns the number of elements encountered.

Count([1 2 3]) → 3
Count([]) → 0

func Exhaust

func Exhaust[T any](i Iterator[T])

Exhaust exhausts the iterator ignoring any elements in it.

func ForEach

func ForEach[T any](i Iterator[T], f func(T))

ForEach calls the provided function on every element of an iterator, exhausting it.

ForEach([1 2 3], fmt.Print)
 // Prints "123"

func ForEachWithError

func ForEachWithError[T any](i Iterator[T], f func(T) error) error

ForEachWithError calls the provided function on every element of an iterator, stopping once f returns an error or the iterator is exhausted.

Errors from the iterator are not checked.

func Foo(i int) error {
	if i < 0 {
		return errors.New("i can't be negative")
	}
	fmt.Print(i)
	return nil
}
i := ForEachWithError([1 -1 2], Foo)
// Prints "1"
i.Err() → "i can't be negative"

This function short-circuits and may not exhaust the provided iterator.

func IntoChannel

func IntoChannel[T any](i Iterator[T]) <-chan T

IntoChannel spawns a new goroutine which sends all elements from an iterator over a returned channel.

After the iterator is exhausted the returned channel is closed.

If the provided iterator implements VolatileIterator, uses GetCopy() instead of Get().

func IntoMap

func IntoMap[K comparable, V any](i Iterator[Pair[K, V]]) map[K]V

IntoMap collects all elements from an iterator into a map.

If the provided iterator implements VolatileIterator, uses GetCopy() instead of Get().

func IntoSlice

func IntoSlice[T any](i Iterator[T]) []T

IntoSlice collects all elements from an iterator into a single slice.

If the provided iterator implements VolatileIterator, uses GetCopy() instead of Get().

func IntoString

func IntoString(i Iterator[rune]) string

IntoString collects all codepoints and returns a UTF-8 string containing those codepoints.

If the provided iterator implements VolatileIterator, uses GetCopy() instead of Get().

func Max

func Max[T constraints.Ordered](i Iterator[T]) (max T, ok bool)

Max returns the biggest element from the iterator, as by the `>` operator.

If the iterator contains no elements, returns the zero value for T and `ok` is set to false.

Max([2 5 1 9 3]) → (9, true)
Max([]) → (0, false)

func MaxFunc

func MaxFunc[T any](i Iterator[T], greater func(T, T) bool) (max T, ok bool)

MaxFunc returns the biggest element from the iterator, using greater as the comparator.

If the iterator contains no elements, returns the zero value for T and `ok` is set to false.

type Person struct { Name string; Age int }
people := []Person{{"Alice", 30}, {"Bob", 25}, {"Charlie", 41}}
MaxFunc(people, (p1, p2) => p1.Age > p2.Age) → (Person{"Charlie", 41}, true)
MaxFunc([], (p1, p2) => p1.Age > p2.Age) → (Person{"", 0}, false)

func Min

func Min[T constraints.Ordered](i Iterator[T]) (min T, ok bool)

Min returns the smallest element from the iterator, as by the `<` operator.

If the iterator contains no elements, returns the zero value for T and `ok` is set to false.

Min([2 5 1 9 3]) → (1, true)
Min([]) → (0, false)

func MinFunc

func MinFunc[T any](i Iterator[T], less func(T, T) bool) (min T, ok bool)

MinFunc returns the smallest element from the iterator, using less as the comparator.

If the iterator contains no elements, returns the zero value for T and `ok` is set to false.

type Person struct { Name string; Age int }
people := []Person{{"Alice", 30}, {"Bob", 25}, {"Charlie", 41}}
MinFunc(people, (p1, p2) => p1.Age < p2.Age) → (Person{"Bob", 25}, true)
MinFunc([], (p1, p2) => p1.Age < p2.Age) → (Person{"", 0}, false)

func None

func None(i Iterator[bool]) bool

None returns true if all elements from the iterator are false.

None([false true false]) → false
None([false false]) → true
None([true true]) → false
None([]) → true

See functions Any and None; or NoneFunc which accepts objects of arbitrary type.

This function short-circuits and may not exhaust the provided iterator.

func NoneFunc

func NoneFunc[T any](i Iterator[T], f func(T) bool) bool

NoneFunc returns true if all for all elements `f(elem)` returns false.

type Person struct { Name string; Age int }
NoneFunc([Person{"Alice", 30} Person{"Bob", 16}], p => p.Age >= 18) → false
NoneFunc([Person{"Bob", 16} Person{"Charlie", 17}], p => p.Age >= 18) → true
NoneFunc([Person{"Alice", 30} Person{"Deborah", 47]), p => p.Age >= 18 → false
NoneFunc([], p => p.Age >= 18) → true

See functions AnyFunc and AllFunc; or None which accepts iterators over booleans.

This function short-circuits and may not exhaust the provided iterator.

func Product

func Product[T Numeric](i Iterator[T]) T

Product returns the result of multiplying all elements in an iterator.

Equivalent to `ReduceWithInitial(i, (a, b) => a * b, 1)`, but removes the function call for every element.

Product([1 2 3]) → 6
Product([3+0i 1i]) → 3i
Product([]) → 1

func Reduce

func Reduce[T any](i Iterator[T], f func(accumulator T, element T) T) (r T, ok bool)

Reduce returns the result of repeatedly applying a binary function.

The first call to the provided function is done with the 1st and 2nd element of the iterable.

If the iterator has only one element, this function simply returns it. If the iterator is empty, sets ok to false and returns a zero value for T.

Assuming that the function provided is summation (`(a, b) => a + b`), these are the results of Reduce:

Reduce([1 2 3 4 5], sum) → (15, true)
Reduce([1], sum) → (1, true)
Reduce([], sum) → (0, false)

See function ReduceWithInitial, which is accepts an initial accumulator value.

See function Accumulate, which also returns partial results.

func ReduceWithInitial

func ReduceWithInitial[T, R any](i Iterator[T], f func(accumulator R, element T) R, initial R) R

ReduceWithInitial returns he result of repeatedly applying a binary function, starting with the provided initial value.

Assuming that the function provided is summation (`(a, b) => a + b`), these are the results of ReduceWithInitial:

ReduceWithInitial([1 2 3 4 5], sum, 0) → 15
ReduceWithInitial([1 2 3 4 5], sum, 5) → 20
ReduceWithInitial([1], sum, 5) → 6
ReduceWithInitial([], sum, 5) → 5

See function Reduce, which is assumes the first value of an iterator is the initial accumulator value.

See function AccumulateWithInitial, which also returns partial results.

func SendOver

func SendOver[T any](i Iterator[T], out chan<- T)

SendOver sends all elements from an iterator over a provided channel. Blocks until the iterator is exhausted. The provided channel is *not* closed.

If the provided iterator implements VolatileIterator, uses GetCopy() instead of Get().

func Sum

func Sum[T Numeric](i Iterator[T]) T

Sum returns the result of adding all elements of the iterable.

Equivalent to `ReduceWithInitial(i, (a, b) => a + b, 0)`, but removes the function call for every element.

Sum([1 2 3]) → 6
Sum([3+0i 1i]) → 3+1i
Sum([]) → 0

Types

type IOReader

type IOReader[T any] interface {
	Read() (T, error)
}

IOReader is an interface satisfied by objects which incrementally pull elements from an IO stream.

The Read() method must return (nil, io.EOF) once no more elements are available.

An example of IOReader implementation is [csv.Reader].

type Iterable

type Iterable[T any] interface {
	Iter() Iterator[T]
}

Iterable represents any user-defined struct which can be iterated over.

Slices, maps, channels and strings can also be iterated, but in order to get an iterator use one of the OverXxx methods.

type Iterator

type Iterator[T any] interface {
	// Next tries to advance the iterator to the next element,
	// or the first element if it's the first call.
	//
	// Returns true if there's an element available.
	//
	// Must not be called for the second time after false is returned.
	Next() bool

	// Get retrieves the current element of the iterator.
	//
	// Must not be called after Next() returned false.
	//
	// While it is not forbidden to call Get() multiple times without advancing
	// the iterator, is is strongly advised not to do so. Calls to Get()
	// can be arbitrarily complex; see e.g. [Map].
	//
	// All functionalities in the iter module ensure only a single call to Get() is made,
	// as long as the caller also makes a single call to Get().
	//
	// If an Iterator also implements [VolatileIterator], subsequent calls to Get()
	// may return the same element (usually a slice), just mutated.
	Get() T

	// Err returns any error encountered by the iterator.
	//
	// Must not be called before Next() returns false.
	//
	// Some iterator may never error out, and their Err() method may always return nil.
	// See the documentation of relevant iterators.
	Err() error
}

Iterator represents a state of iteration over elements of type T.

Iterators should start in a state before-the-first-element, as iteration is performed in the following pattern:

for iterator.Next() {
	elem := iterator.Get()
}
err := iterator.Err()

func Accumulate

func Accumulate[T any](i Iterator[T], f func(accumulator T, element T) T) Iterator[T]

Accumulate returns an iterator over accumulated ("partial") results of applying a binary function.

Assuming that the function provided is summation (`(a, b) => a + b`), these are the results of Accumulate:

Accumulate([1 2 3 4 5], sum) → [1 3 6 10 15]
Accumulate([1], sum) → [1]
Accumulate([], sum) → []

See function AccumulateWithInitial, which is accepts an initial accumulator value.

See function Reduce, which only returns the last element.

func AccumulateWithInitial

func AccumulateWithInitial[T, R any](i Iterator[T], f func(accumulator R, element T) R, initial R) Iterator[R]

AccumulateWithInitial returns an iterator over accumulated ("partial") results of applying a binary function, starting with the provided initial value.

Assuming that the function provided is summation (`(a, b) => a + b`), these are the results of AccumulateWithInitial:

AccumulateWithInitial([1 2 3 4 5], sum, 0) → [0 1 3 6 10 15]
AccumulateWithInitial([1 2 3 4 5], sum, 5) → [5 6 8 11 15 20]
AccumulateWithInitial([1], sum, 5) → [5 6]
AccumulateWithInitial([], sum, 5) → [5]

See function Accumulate, which is assumes the first element of an iterator is the initial accumulator value.

See function ReduceWithInitial, which only returns the last element.

func CartesianProduct

func CartesianProduct[T any](outer ...[]T) Iterator[[]T]

CartesianProduct generates the cartesian product of the inner slices. Equivalent to nested for loops.

If the outer slice or any of the inner slices are empty, returns an empty iterator.

CartesianProduct("ABC", "xy") → ["Ax" "Ay" "Bx" "By" "Cx" "Cy"]
CartesianProduct("AB", "xy", "12")
→ ["Ax1" "Ax2" "Ay1" "Ay2" "Bx1" "Bx2" "By1" "By2" "Cx1" "Cx2" "Cy1" "Cy2"]
CartesianProduct("ABC", "") → []
CartesianProduct() → []

Subsequent calls to Get() return the same slice, but mutated. See VolatileIterator.

See CartesianProductIter, which accepts an iterator over iterators.

The Err() method always returns nil.

func CartesianProductIter

func CartesianProductIter[T any](i Iterator[Iterator[T]]) Iterator[[]T]

CartesianProductIter collects the outer iterator and all inner iterators into slices, and generates the cartesian product of provided inner iterables.

If the outer iterator or any of the inner slices are empty, returns an empty iterator.

CartesianProductIter(["ABC", "xy"]) → ["Ax" "Ay" "Bx" "By" "Cx" "Cy"]
CartesianProductIter(["AB" "xy" "12"])
→ ["Ax1" "Ax2" "Ay1" "Ay2" "Bx1" "Bx2" "By1" "By2" "Cx1" "Cx2" "Cy1" "Cy2"]
CartesianProductIter(["ABC" ""]) → []
CartesianProductIter([]) → []

Subsequent calls to Get() return the same slice, but mutated. See VolatileIterator.

See CartesianProduct, which accepts a slice of slices.

The Err() method always returns nil.

func Chain

func Chain[T any](its ...Iterator[T]) Iterator[T]

Chain returns all elements from the provided iterators, in order. Also called "Flatten" in other languages.

Chain([1 2], [3 4], [5 6]) → [1 2 3 4 5 6]

See also ChainFromIterator, which lazily retrieves next iterators.

func ChainFromIterator

func ChainFromIterator[T any](its Iterator[Iterator[T]]) Iterator[T]

ChainFromIterator returns all elements from all iterators generated by `its`. As opposed to Chain, next iterator are retrieved lazily, which allows an infinite number of inner iterators.

ChainFromIterator([[1 2] [3 4] [5 6]]) → [1 2 3 4 5 6]

See also Chain, which explicitly takes iterators to chain together.

func ChainMap

func ChainMap[T, U any](i Iterator[T], f func(T) Iterator[U]) Iterator[U]

ChainMap is an implementation of 2 operations: Map, then Chain; returns all values returned from iterators returned by calling f on every element of i.

ChainMap([1 5 10], x => [x, x + 2]) → [1 3 5 7 10 12]

func Combinations

func Combinations[T any](r int, items ...T) Iterator[[]T]

Combinations generates all r-length subsequences of provided items, where each element may only appear once.

Generated combinations are returned in lexicographical order (as defined by the input ordering). Elements are considered unique based on their index.

Panics if r is negative.

Combinations(2, 'a', 'b', 'c', 'd') → ["ab" "ac" "ad" "bc" "bd" "cd"]
Combinations(3, 'a', 'b', 'c', 'd') → ["abc" "abd" "acd" "bcd"]
Combinations(0, 'a', 'b', 'c') → [[]]
Combinations(0) → [[]]
Combinations(3, 'a', 'b') → []
Combinations(3) → []

Subsequent calls to Get() return the same slice, but mutated. See VolatileIterator.

See also CombinationsIter, which accepts an iterator; or CombinationsWithReplacement, which allows elements to appear multiple times in a subsequence. To generate all r-length combinations use PowerSet.

The Err() method always returns nil.

func CombinationsIter

func CombinationsIter[T any](items Iterator[T], r int) Iterator[[]T]

CombinationsIter collects the items into a slice and then generates all r-length subsequences of provided items, where each element may only appear once.

Generated combinations are returned in lexicographical order (as defined by the input ordering).

Panics if r is negative, generates a single empty sequence if r == 0, returns an empty sequence if r > len(items).

CombinationsIter("abcd", 2) → ["ab" "ac" "ad" "bc" "bd" "cd"]
CombinationsIter("abcd", 3) → ["abc" "abd" "acd" "bcd"]
CombinationsIter("abc", 0) → [[]]
CombinationsIter("", 0) → [[]]
CombinationsIter("ab", 3) → []
CombinationsIter("", 3) → []

Subsequent calls to Get() return the same slice, but mutated. See VolatileIterator.

See also Combinations, which accepts a slice of elements; or CombinationsWithReplacementIter, which allows elements to appear multiple times in a subsequence. To generate all r-length combinations use PowerSetIter.

The Err() method always returns nil.

func CombinationsWithReplacement

func CombinationsWithReplacement[T any](r int, items ...T) Iterator[[]T]

CombinationsWithReplacement generates all r-length subsequences of provided items, where each element may appear multiple times in the subsequence.

Generated combinations are returned in lexicographical order (as defined by the input ordering).

Panics if r is negative, generates a single empty sequence if r == 0, returns an empty sequence if r > len(items).

CombinationsWithReplacement(2, 'a', 'b', 'c') → ["aa" "ab" "ac" "bb" "bc" "cc"]
CombinationsWithReplacement(3, 'a', 'b', 'c')
→ ["aaa" "aab" "aac" "abb" "abc" "acc" "bbb" "bbc" "bcc" "ccc"]
CombinationsWithReplacement(3, 'a', 'b') → ["aaa" "aab" "abb" "bbb"]
CombinationsWithReplacement(0, 'a', 'b') → [[]]
CombinationsWithReplacement(0) → [[]]
CombinationsWithReplacement(2) → []

Subsequent calls to Get() return the same slice, but mutated. See VolatileIterator.

See also CombinationsWithReplacementIter, which accepts an iterator; or Combinations, which does not allow an element to appear multiple times in the subsequence.

The Err() method always returns nil.

func CombinationsWithReplacementIter

func CombinationsWithReplacementIter[T any](items Iterator[T], r int) Iterator[[]T]

CombinationsWithReplacementIter collects all items into a slice and then generates all r-length subsequences of provided items, where each element may appear multiple times in the subsequence.

Generated combinations are returned in lexicographical order (as defined by the input ordering).

Panics if r is negative.

CombinationsWithReplacementIter("abc", 2) → ["aa" "ab" "ac" "bb" "bc" "cc"]
CombinationsWithReplacementIter("abc", 3)
→ ["aaa" "aab" "aac" "abb" "abc" "acc" "bbb" "bbc" "bcc" "ccc"]
CombinationsWithReplacementIter("ab", 3) → ["aaa" "aab" "abb" "bbb"]
CombinationsWithReplacementIter("ab", 0) → [[]]
CombinationsWithReplacementIter("", 0) → [[]]
CombinationsWithReplacementIter("", 2) → []

Subsequent calls to Get() return the same slice, but mutated. See VolatileIterator.

See also CombinationsWithReplacement, which accepts a slice; or CombinationsIter, which does not allow an element to appear multiple times in the subsequence.

The Err() method always returns nil.

func Compress

func Compress[T any](i Iterator[T], selectors Iterator[bool]) Iterator[T]

Compress returns elements from i, for which the corresponding element from selectors is true.

Functionally equivalent to Pairwise + Filter, while also discarding the selector.

Compress([1 2 3 4], [true false true false]) → [1 3]

See also the CompressFunc function.

func CompressFunc

func CompressFunc[T, U any](i Iterator[T], selectors Iterator[U], pred func(U) bool) Iterator[T]

CompressFunc returns elements from i, if calling predicate on the corresponding element from selectors returns true.

Similar functionally may be achieved with Pairwise + Filter, while also discarding the selector.

CompressFunc(["a" "b" "c" "d"], [1, 2, 3, 4], isEven) → ["b" "d"]

See Compress, if selectors is already an iterator of booleans.

func ConsecutivePairs

func ConsecutivePairs[T any](i Iterator[T]) Iterator[[2]T]

ConsecutivePairs generates successive overlapping pairs of elements from the iterator.

ConsecutivePairs([1 2 3 4]) → [[1 2] [2 3] [3 4]]
ConsecutivePairs([1]) → []
ConsecutivePairs([]) → []

func Cycle

func Cycle[T any](n int, items ...T) Iterator[T]

Cycle cycles trough the provided elements `n` times.

Cycle(3, "a", "b", "c") → ["a" "b" "c" "a" "b" "c" "a" "b" "c"]
Cycle(0, "a", "b", "c") → []
Cycle(2) → []

Panics if n is negative.

See also Repeat which cycles indefinitely and CycleIter which accepts an Iterator.

The Err() method always returns nil.

func CycleIter

func CycleIter[T any](i Iterator[T], n int) Iterator[T]

CycleIter collects elements from the iterator into a slice, and then cycles trough elements of the provided iterator `n` times.

Equivalent to `Cycle(n, IntoSlice(i)...)`.

CycleIter("abc", 3) → "abcabcabc"
CycleIter("abc", 0) → ""
CycleIter("", 2) → ""

See also Cycle and RepeatIter which cycles indefinitely.

The Err() method always returns nil.

func DropWhile

func DropWhile[T any](i Iterator[T], pred func(T) bool) Iterator[T]

DropWhile drops the first elements for which `pred(elem)` is true. Afterwards, all elements are returned (regardless for the result of pred)

DropWhile([1 2 3 2 1], x => x < 3) → [3 2 1]
DropWhile([1 2 3 2 1], x => x < 5) → []
DropWhile([1 2 3 2 1], x => x < 0) → [1 2 3 2 1]

func Empty

func Empty[T any]() Iterator[T]

Empty returns an iterator which never generates any elements, and which never returns an error.

func Enumerate

func Enumerate[T any](i Iterator[T], start int) Iterator[Pair[int, T]]

Enumerate generates pairs of elements from i and their corresponding indices (offset by start).

Enumerate(["a" "b" "c"], 0) → [Pair{0 "a"} Pair{1 "b"} Pair{2 "c"}] Enumerate(["a" "b" "c"], 42) → [Pair{42 "a"} Pair{43 "b"} Pair{44 "c"}]

func Error

func Error[T any](err error) Iterator[T]

Error returns an iterator, which never generates any elements, but whose Err method returns a provided error.

func Filter

func Filter[T any](i Iterator[T], keep func(T) bool) Iterator[T]

Filter returns an iterator over elements for which `keep(elem)` returns true.

Filter([1 2 3 4 5 6], isOdd) → [1 3 5] Filter([2 4 6], isOdd) → []

func GroupBy

func GroupBy[T any, K comparable](i Iterator[T], key func(T) K) Iterator[Pair[K, Iterator[T]]]

GroupBy generates consecutive runs of elements for which `key(elem)` is the same.

If a consecutive run for a particular key should be generated only once, ensure the input is sorted by the key function. This differs from SQL's GROUP BY construct - this function behaves like the POSIX `uniq` utility.

The group iterator is shared with the GroupBy iterator, so a group is no longer available after advancing to the next key.

names := ["Alice" "Adam" "Amelia" "Andrew" "Bob" "Brian" "Casey" "Chloe" "Craig"]
GroupBy(names, name => name[0])
→ [{"A" ["Alice" "Adam" "Amelia" "Andrew"]} {"B" ["Bob" "Brian"]} {"C" ["Casey" "Chloe" "Craig"]}]

names := ["Alice" "Andrew" "Bob" "Casey" "Adam" "Amelia" "Chloe" "Craig" "Brian"]
GroupBy(names, name => name[0])
→ [{"A" ["Alice" "Andrew"]} {"B" ["Bob"]} {"C" ["Casey"]} {"A" ["Adam" "Amelia"]} {"C" ["Chloe" "Craig"]} {"B" ["Brian"]}]

See GroupByFunc, for a function allowing custom key comparisons.

func GroupByFunc

func GroupByFunc[T, K any](i Iterator[T], key func(T) K, eq func(K, K) bool) Iterator[Pair[K, Iterator[T]]]

GroupByFunc generates consecutive runs of elements for which `eq(key(elem1), key(elem2))` is true.

If a consecutive run for a particular key should be generated only once, ensure the input is sorted by the key function. This differs from SQL's GROUP BY construct - this function behaves like the POSIX `uniq` utility.

The group iterator is shared with the GroupByFunc iterator, so a group is no longer available after advancing to the next key.

See GroupBy if K is already comparable.

func InfiniteRange

func InfiniteRange[T Numeric]() Iterator[T]

InfiniteRange generates every number starting from 0, adding 1 on every iteration, equivalent to InfiniteRangeWithStep(0, 1).

The iterator performs addition on every step, which may lead to accumulating floating-point inaccuracy for non-integer types.

InfiniteRange[int]() → [0 1 2 ... math.MaxInt math.MinInt ... -1 0 1 ...]
InfiniteRange[uint]() → [0 1 2 ... math.MaxUint 0 ...]

See also InfiniteRangeFrom and InfiniteRangeWithStep and the Range family of functions.

The Err() method always returns nil.

func InfiniteRangeFrom

func InfiniteRangeFrom[T Numeric](start T) Iterator[T]

InfiniteRangeFrom generates every number starting from the provided number, adding 1 on every iteration. Equivalent to InfiniteRangeWithStep(start, 1).

The iterator performs addition on every step, which may lead to accumulating floating-point inaccuracy for non-integer types.

InfiniteRangeFrom[int](10) → [10 11 12 ... math.MaxInt math.MinInt ... -1 0 1 ...]
InfiniteRangeFrom[uint](10) → [10 11 12 ... math.MaxUint 0 1 ...]

See also InfiniteRange and InfiniteRangeWithStep and the Range family of functions.

The Err() method always returns nil.

func InfiniteRangeWithStep

func InfiniteRangeWithStep[T Numeric](start, delta T) Iterator[T]

InfiniteRangeWithStep generates every number starting from the `start` adding `delta` on every step.

The iterator performs addition on every step, which may lead to accumulating floating-point inaccuracy for non-integer types.

InfiniteRangeWithStep[int](10, 2) → [10 12 14 ... math.MaxInt-1 math.MinInt ... 8 10 12 ...]
InfiniteRangeWithStep[int](10, -2) → [10 8 6 ... math.MinInt math.MaxInt-1 ... 12 10 8 ...]
InfiniteRangeWithStep[uint](10, 2) → [10 12 14 ... math.MaxUint-1 0 ... 8 10 12 ...]

See also InfiniteRange and InfiniteRangeFrom and the Range family of functions.

The Err() method always returns nil.

func Limit

func Limit[T any](i Iterator[T], n int) Iterator[T]

Limit generates up to n first elements from the provided iterator.

Panics if n is negative.

Limit([1 2 3 4 5], 3) → [1 2 3]
Limit([1 2 3], 5) → [1 2 3]
Limit([1 2 3], 0) → []

See functions Skip and Slice.

This function short-circuits and may not exhaust the provided iterator.

func Map

func Map[T, U any](i Iterator[T], f func(T) U) Iterator[U]

Map generates the results of applying a function to every element of an iterable.

Every call to Get() results in a call to `f` - which might pose a problem if `f` may have side effects. All functionality from the iter module guarantees a single call to Get() if the caller also performs only a single call to Get() per iteration.

Map([1 2 3], x => x + 5) → [6 7 8]

func MapWithError

func MapWithError[T, U any](i Iterator[T], f func(T) (U, error)) Iterator[U]

MapWithError generates the results of applying a function to every element of an iterable, stopping once the function returns an error.

func Foo(i int) (int, error) {
	if i < 0 {
		return 0, errors.New("i can't be negative")
	}
	return i + 5, nil
}
MapWithError([1 2 -1 -2 3 4], Foo) → [6 7]
// iterator's Err() returns "i can't be negative"

func Over

func Over[T any](s ...T) Iterator[T]

Over returns an iterator over the provided elements.

Equivalent to OverSlice.

The Err() method always returns nil.

func OverChannel

func OverChannel[T any](ch <-chan T) Iterator[T]

OverChannel returns an iterator over channel elements.

Note that it may be possible to leak goroutines if the iterator is not exhausted. See consumer documentation whether they short-circuit and leave iterators non-exhausted. The leak may happen if the producer goroutine(s) assume that all elements will be received before exiting, e.g.:

go func(){
	for i := 0; i < 100; i++ {
		ch <- i
	}
	close(ch)
}()

The Next() method blocks until an element is available.

The Err() method always returns nil.

func OverIOReader

func OverIOReader[T any](r IOReader[T]) Iterator[T]

OverIOReader wraps an IOReader into an Iterator.

See IOReader for a more detailed explanation; but an example implementation of an IOReader is [csv.Reader].

func OverMap

func OverMap[K comparable, V any](m map[K]V) Iterator[Pair[K, V]]

OverMap returns an iterator over key-values pair of a map.

Elements are generated in an arbitrary order.

The Err() method always returns nil.

func OverMapKeys

func OverMapKeys[K comparable, V any](m map[K]V) Iterator[K]

OverMapKeys returns an iterator over keys of a map.

Keys are generated in an arbitrary order.

The Err() method always returns nil.

func OverMapValues

func OverMapValues[K comparable, V any](m map[K]V) Iterator[V]

OverMapValues returns an iterator over values of a map.

Keys are generated in an arbitrary order.

The Err() method always returns nil.

func OverSlice

func OverSlice[T any](s []T) Iterator[T]

OverSlice returns an iterator over slice elements.

The Err() method always returns nil.

func OverString

func OverString(s string) Iterator[rune]

OverString returns an iterator over UTF-8 codepoints in the string.

If the string contains invalid UTF-8 sequences, the replacement character (U+FFFD) is returned, and iteration advances over a single byte.

The Err() method always returns nil.

func Pairwise

func Pairwise[T, U any](ts Iterator[T], us Iterator[U]) Iterator[Pair[T, U]]

Pairwise returns pairs of corresponding elements from ts and us.

Stops once any of the iterators is exhausted.

Pairwise([1 2 3], ["a" "b" "c"]) → [{1 "a"} {2 "b"} {3 "c"}]
Pairwise([1 2 3], ["a"]) → [{1 "a"}]
Pairwise([], ["a" "b"]) → []

See Zip for a similar operation on an arbitrary number of homogenous iterators, or PairwiseLongest for an operation which stops only when all iterators are exhausted (and does not short-circuit).

This function short-circuits and may not exhaust the provided iterator.

func PairwiseLongest

func PairwiseLongest[T, U any](ts Iterator[T], us Iterator[U], tFill T, uFill U) Iterator[Pair[T, U]]

PairwiseLongest returns pairs of corresponding elements from ts and us.

Stops once both of the iterators are exhausted, even if one of the iterators returns an error.

If there are different amount of elements in the provided iterators, uses tFill or uFill values in place of the exhausted iterator's elements.

PairwiseLongest([1 2 3], ["a" "b" "c"], 0, "-") → [{1 "a"} {2 "b"} {3 "c"}]
PairwiseLongest([1 2 3], ["a"], 0, "-") → [{1 "a"} {2 "-"} {3 "-"}]
PairwiseLongest([], ["a" "b"], 0, "-") → [{0 "a"} {0 "b"}]
PairwiseLongest(Error(someErr), ["a" "b"], 0, "-") → [{0 "a"} {0 "b"}]

See ZipLongest for a similar operation on an arbitrary number of homogenous iterators, or Pairwise which stops when one of the iterators is exhausted.

func Permutations

func Permutations[T any](r int, items ...T) Iterator[[]T]

Permutations generates all r-length permutations (different orderings) of the provided items.

Generated combinations are returned in lexicographical order (as defined by the input ordering).

Panics if r is negative, generates a single empty sequence if r == 0, returns an empty sequence if r > len(items).

Permutations(3, 'a', 'b', 'c') → ["abc" "acb" "bac" "bca" "cab" "cba"]
Permutations(2, 'a', 'b', 'c') → ["ab" "ac" "ba" "bc" "ca" "cb"]
Permutations(0, 'a', 'b', 'c') → [[]]
Permutations(0) → [[]]
Permutations(4, 'a', 'b', 'c') → []
Permutations(4) → []

Subsequent calls to Get() return the same slice, but mutated. See VolatileIterator.

See also [PermutationsIter], which accepts an iterator.

The Err() method always returns nil.

func PermutationsIter

func PermutationsIter[T any](i Iterator[T], r int) Iterator[[]T]

PermutationsIter collects all items into a slice, and then generates all r-length permutations (different orderings) of the provided items.

Generated combinations are returned in lexicographical order (as defined by the input ordering).

Panics if r is negative, generates a single empty sequence if r == 0, returns an empty sequence if r > len(items).

PermutationsIter("abc", 3) → ["abc" "acb" "bac" "bca" "cab" "cba"]
PermutationsIter("abc", 2) → ["ab" "ac" "ba" "bc" "ca" "cb"]
PermutationsIter("abc", 0) → [[]]
PermutationsIter(0) → [[]]
PermutationsIter("abc", 3) → []
PermutationsIter(3) → []

Subsequent calls to Get() return the same slice, but mutated. See VolatileIterator.

See also [Permutations], which accepts a slice of elements.

The Err() method always returns nil.

func PowerSet

func PowerSet[T any](items ...T) Iterator[[]T]

PowerSet generates all subsets of the provided elements.

Only up to 63 elements are supported - larger power sets are deemed unpractical and impossible to iterate - they contain more than quintillion (10^18) elements.

PowerSet() → [[]]
PowerSet(1) → [[] [1]]
PowerSet(1, 2) → [[] [1] [2] [1 2]]
PowerSet(1, 2, 3) → [[] [1] [2] [1 2] [3] [1 3] [2 3] [1 2 3]]

Subsequent calls to Get() return the same slice, but mutated. See VolatileIterator.

See PowerSetIter, which accepts an iterator.

The Err() method always returns nil.

func PowerSetIter

func PowerSetIter[T any](i Iterator[T]) Iterator[[]T]

PowerSetIter collects all elements into a slice, then generates all subsets of the elements.

Only up to 63 elements are supported - larger power sets are deemed unpractical and impossible to iterate - they contain more than quintillion (10^18) elements.

PowerSetIter([]) → [[]]
PowerSetIter([1 2]) → [[] [1] [2] [1 2]]
PowerSetIter([1 2 3]) → [[] [1] [2] [1 2] [3] [1 3] [2 3] [1 2 3]]

Subsequent calls to Get() return the same slice, but mutated. See VolatileIterator.

See PowerSet, which accepts a slice directly.

The Err() method always returns nil.

func Range

func Range[T NumericComparable](stop T) Iterator[T]

InfiniteRange generates every number starting from 0, adding 1 on every iteration, as long as the current value is smaller than `stop`. Equivalent to RangeWithStep(0, stop, 1).

The iterator performs addition on every step, which may lead to accumulating floating-point inaccuracy for non-integer types.

Range(5) → [0 1 2 3 4]
Range(0) → []

See also RangeFrom and RangeWithStep and the family of InfiniteRange functions.

The Err() method always returns nil.

func RangeFrom

func RangeFrom[T NumericComparable](start, stop T) Iterator[T]

RangeFrom generates every number starting from `start`, adding 1 on every iteration, as long as the current value is smaller than `stop`. Equivalent to RangeWithStep(start, stop, 1).

The iterator performs addition on every step, which may lead to accumulating floating-point inaccuracy for non-integer types.

Range(5, 10) → [5 6 7 8 9]
Range(5, 5) → []

See also Range and RangeWithStep and the family of InfiniteRange functions.

The Err() method always returns nil.

func RangeWithStep

func RangeWithStep[T NumericComparable](start, stop, delta T) Iterator[T]

RangeWithStep generates every number starting from `start`, adding `delta` on every iteration, as long as the current value is smaller than `stop`.

The iterator performs addition on every step, which may lead to accumulating floating-point inaccuracy for non-integer types.

RangeWithStep(5, 11, 2) → [5 7 9]
RangeWithStep(5, 12, 2) → [5 7 9 11]
RangeWithStep(5, 5, 2) → [5 7 9 11]

See also Range and RangeFrom and the family of InfiniteRange functions.

The Err() method always returns nil.

func Repeat

func Repeat[T any](items ...T) Iterator[T]

Repeat cycles through given elements indefinitely.

Repeat(1 2 3) → [1 2 3 1 2 3 1 2 3 ...]
Repeat(1) → [1 1 1 ...]

Panics if there are no elements.

See also RepeatIter, which accepts an iterator and Cycle, which stops after given number of cycles.

The Err() method always returns nil.

func RepeatIter

func RepeatIter[T any](i Iterator[T]) Iterator[T]

RepeatIter collects items from i into a slice, and cycles through them indefinitely.

RepeatIter([1 2 3]) → [1 2 3 1 2 3 1 2 3 ...]
RepeatIter([1]) → [1 1 1 ...]

Equivalent to `Repeat(IntoSlice(i)...)`

Panics if there are no elements.

See also Repeat and CycleIter, which stops after given number of cycles.

The Err() method always returns nil.

func RepeatedlyApply

func RepeatedlyApply[T any](f func(T) T, v T) Iterator[T]

RepeatedlyApply generates an infinite sequence of continuously applying the provided function to its output, starting with `v`.

RepeatedlyApply(x => x + 5, 0) → [0 5 10 15 20 25 ...]

func Skip

func Skip[T any](i Iterator[T], n int) Iterator[T]

Skip returns an iterator without the first `n` elements.

Panics if n is negative.

Skip([1 2 3 4 5], 2) → [3 4 5]
Skip([1 2 3], 5) → []

See functions Limit and Slice.

func Slice

func Slice[T any](i Iterator[T], start, stop int) Iterator[T]

Slice returns an iterator without the first `start` elements and without the last `stop` elements; applying Skip and Limit.

Panics if start or stop are negative; or if start is greater than stop.

Slice([1 2 3 4 5], 1, 3) → [2 3]
Slice([1 2 3 4 5], 0, 3) → [1 2 3] // Use Limit(..., 3)
Slice([1 2 3 4 5], 2, 5) → [3 4 5] // Use Skip(..., 2)
Slice([1 2 3 4 5], 3, 3) → [] // Use Empty[T]()

See functions Limit and Skip.

This function short-circuits and may not exhaust the provided iterator.

func Sort

func Sort[T constraints.Ordered](i Iterator[T]) Iterator[T]

Sort collects all elements of an iterator into a slice, and the sorts it with the help of slices.Sort.

Because of the assumption made by slices.Sort, strict weak ordering is required. Such ordering is not satisfied, e.g. when floating point NaN values are present; in that case use `SortFunc(x, func(a, b float64) bool {return a < b || (math.IsNaN(a) && !math.IsNaN(b))})`.

Sort([2 3 1 0]) → [0 1 2 3]

func SortFunc

func SortFunc[T any](i Iterator[T], less func(T, T) bool) Iterator[T]

SortFunc collects all elements of an iterator into a slice, and the sorts it using slices.SortFunc with the provided comparator function.

Because of the assumption made by slices.Sort, strict weak ordering is required. Such ordering is not satisfied by the `<` operator when floating point NaN values are present; in that case use `func(a, b float64) bool {return a < b || (math.IsNaN(a) && !math.IsNaN(b))}`, as the comparator function.

people := []Person{{"Alice", 30}, {"Bob", 25}, {"Charlie", 41}}
SortFunc(people, p => p.age) → [{"Bob", 25}, {"Alice", 30}, {"Charlie", 41}]

func SortStableFunc

func SortStableFunc[T any](i Iterator[T], less func(T, T) bool) Iterator[T]

SortStableFunc collects all elements of an iterator into a slice, and the sorts it while keeping the relative order of equal elements using slices.SortStableFunc with the provided comparator function.

Because of the assumption made by slices.Sort, strict weak ordering is required. Such ordering is not satisfied by the `<` operator when floating point NaN values are present; in that case use `func(a, b float64) bool {return a < b || (math.IsNaN(a) && !math.IsNaN(b))}`, as the comparator function.

func SplitOn

func SplitOn[T any](i Iterator[T], shouldSplit func(T) bool) Iterator[Iterator[T]]

SplitOn splits an iterator into multiple iterators, separated by runs of elements for which shouldSplit returns true.

The inner iterator is shared with the SplitOn iterator, so the inner "words" are not available after calling splitOnIterator.Next().

Functionally equivalent to GroupBy + Filter, while also discarding the boolean "keys".

SplitOn("foo bar baz", unicode.IsSpace) → ["foo" "bar" "baz"]
SplitOn("foo   bar  baz  ", unicode.IsSpace) → ["foo" "bar" "baz"]
SplitOn("   ", unicode.IsSpace) → []
SplitOn("", unicode.IsSpace) → []

func TakeWhile

func TakeWhile[T any](i Iterator[T], pred func(T) bool) Iterator[T]

TakeWhile returns the first elements for which `pred(elem)` is true. Afterwards, all elements are ignored (regardless for the result of pred).

TakeWhile([1 2 3 2 1], x => x < 3) → [1 2]
TakeWhile([1 2 3 2 1], x => x < 5) → [1 2 3 2 1]
TakeWhile([3 2 1], x => x < 3) → []

This function short-circuits and may not exhaust the provided iterator.

func ToNonVolatile

func ToNonVolatile[T any](i Iterator[T]) Iterator[T]

ToNonVolatile ensures that the returned iterator will return newly-allocated elements on each call to Get().

See the description of VolatileIterator.

For VolatileIterator inputs, returns an iterator whose Get() method calls through to GetCopy(). For other inputs, simply returns the input iterator.

All of the IntoXxx functions automatically call ToNonVolatile.

func Zip

func Zip[T any](its ...Iterator[T]) Iterator[[]T]

Zip returns slices of consecutive elements from all the iterators.

Stops once any of the iterators is exhausted.

Zip("abc", "123", "xyz") → ["a1x" "b2y" "c3z"]
Zip("abc", "12", "x") → ["a1x"]
Zip("abc", "") → []
Zip() → []

See Pairwise for zipping two heterogenous sequences, or ZipLongest which stops only when all iterators are exhausted (and does not short-circuit).

Subsequent calls to Get() return the same slice, but mutated. See VolatileIterator.

This function short-circuits and may not exhaust the provided iterator.

func ZipLongest

func ZipLongest[T any](fill T, its ...Iterator[T]) Iterator[[]T]

ZipLongest returns slices of consecutive elements from all the iterators.

Stops once all of the iterators are exhausted, even if one of the iterators stops with an error. Missing elements (from iterators which were exhausted before others were) are set to `fill`.

Only up to 64 iterators are supported.

ZipLongest('-', "abc", "123", "xyz") → ["a1x" "b2y" "c3z"]
ZipLongest('-', "ab", "123", "x") → ["a1x" "b2-" "-3-"]
ZipLongest('-', "ab", "") → ["a-" "b-"]
ZipLongest(-1, [1 2], Error(someErr)) → [[1 -1] [2 -1]]
ZipLongest('-') → []

Subsequent calls to Get() return the same slice, but mutated. See VolatileIterator.

See PairwiseLongest for zipping two heterogenous sequences, or Zip which stops once any of iterators stops.

type Numeric

type Numeric interface {
	constraints.Integer | constraints.Float | constraints.Complex
}

Numeric is a constraint that permits any type which supports arithmetic operators + - * /. Coincidentally, such types can be constructed from untyped integer constants.

type NumericComparable

type NumericComparable interface {
	constraints.Integer | constraints.Float
}

NumericComparable is a constraint that permits any type which supports arithmetic operators + - * / and comparison operators < <= >= >. Coincidentally, such types can be constructed from untyped integer constants and compared with != and ==.

type Pair

type Pair[T any, U any] struct {
	First  T
	Second U
}

Pair is a utility type containing two possibly heterogenous elements.

Use e.g. by OverMap or Pairwise.

type VolatileIterator

type VolatileIterator[T any] interface {
	Iterator[T]

	// GetCopy() return a (usually shallow) copy of the element,
	// which would be returned by Get().
	GetCopy() T
}

VolatileIterator is an extension of the Iterator protocol, used by iterators, whose return value of Get() is mutated between iterations.

VolatileIterator is usually returned by functions which transform Iterator[T] to Iterator[[]T]. This allows those iterator to skip allocating a new slice with each call to Get().

Use ToNonVolatile if newly-allocated elements are required with each iterator advancement.

Jump to

Keyboard shortcuts

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