goiter

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Aug 15, 2024 License: MIT Imports: 6 Imported by: 1

README

Go Reference Go Report Card codecov GitHub License Test

中文

This package provides a series of iterator creation functions for the range-over-func feature, simplifying the iterator creation logic for users in various common scenarios, such as transformation, filtering, aggregation, sorting, and more.

Why do we need this package?

Although the iterator feature provides us with the ability to iterate over any data structure, the iterator operation functions provided in the standard library are very limited, and the logic for creating iterators is not very intuitive.

Typically, creating an iterator looks like this: you provide a creation function, which returns another function, and the parameter of the returned function is also a function. This is one of the reasons why this feature is controversial in the community.

The purpose of this package is to serve as a foundational toolkit to simplify the logic for creating iterators, reduce scenarios where manual iteration creation is needed, and provide a set of common iterator operation functions for use in higher-level applications.

Requirements

  • go version >= 1.23.0

Examples

Example 1: Traversal of an encapsulated collection

Suppose you need to allow external code to traverse a slice within a struct, but do not want to expose the slice. In this case, you can use the goiter.Slice or goiter.SliceElem function.

goiter.Slice and goiter.SliceElem are similar to the slices.All and slices.Values functions in the standard library, but they also offer reverse traversal capabilities like slices.Backward. You can enable reverse traversal by passing true as the second optional parameter.

package example1

import (
    "fmt"
    "github.com/hsldymq/goiter"
    "iter"
)

type Student struct {
    Name string
    Age  int
}

type School struct {
    students []*Student
}

// Students method returns an iterator that yields each student, rather than directly exposing the internal slice.
func (s *School) Students() goiter.Iterator[*Student] {
    return goiter.SliceElems(s.students)
}

func PrintNames(school *School) {
    // So you can iterate through each student like a regular slice.
    for student := range school.Students() {
        fmt.Println(student.Name)
    }
}
Example 2: Sequence generation
package example2

import (
    "fmt"
    "github.com/hsldymq/goiter"
)

// This function demonstrates how to use the goiter.Range and goiter.RangeStep function.
// goiter.Range and goiter.RangeStep provide similar functionality to Python's range function.
// The difference is that goiter.Range and goiter.RangeStep generate a range of numbers as a closed interval, unlike Python's range function which generates a half-open interval
func RangeDemo() {
    // So this will print 0 1 2 3 4 5, it is equivalent to Python `range(0, 6)` or Golang `for v := range 6`
    for v := range goiter.Range(0, 5) {
        fmt.Printf("%d ", v)
    }
    fmt.Println()

    // This will print 3 2 1 0 -1 -2 -3
    for v := range goiter.Range(3, -3) {
        fmt.Printf("%d ", v)
    }
    fmt.Println()

    // RangeStep function allows you to specify a step value as the third parameter
    // This will print 0 2 4 6 8 10
    for v := range goiter.RangeStep(0, 10, 2) {
        fmt.Printf("%d ", v)
    }
    fmt.Println()

    // This will print 5 3 1 -1 -3 -5
    // When iterating in descending order, you still need to provide a positive step value, so you don't need to adjust the sign of the step based on the direction of the iteration.
    // This is another difference from Python's range function, which requires a negative step value when iterating in reverse.
    // So if you provide a step of 0 or a negative number, RangeStep will not yield any values, 
    for v := range goiter.RangeStep(5, -5, 2) {
        fmt.Printf("%d ", v)
    }
    fmt.Println()
}

// This function demonstrates how to use the goiter.Sequence function.
// goiter.Sequence is general purpose sequence generator, you can use it to generate any sequence you want 
// here is an example of generating Fibonacci sequence
func SequenceDemo() {
    genFib := func(n int) goiter.GeneratorFunc[int] {
        a, b := 0, 1
        return func() (int, bool) {
            if n <= 0 {
                return 0, false
            }
            n--
            a, b = b, a+b
            return a, true
        }
    }

    // this will print first 10 Fibonacci numbers: 1 1 2 3 5 8 13 21 34 55
    for v := range goiter.Sequence(genFib(10)) {
        fmt.Printf("%d ", v)
    }
}
Example 3: Transformation

You can chain an iterator to another iterator for chained processing, so you can implement functions such as data transformation

package example3

import (
    "fmt"
    "github.com/hsldymq/goiter"
    "iter"
)

type Product struct {
    Name string
    Price float64
    Quantity int
}

type Cart struct {
    products []*Product
}

// Checkout demonstrates how to use the goiter Transform function to convert data during iteration.
func (c *Cart) Checkout() goiter.Iterator2[string, float64] {
    // This transformer function creates a new iterator. It converts each product from the source iterator into the corresponding product name and cost.
    return goiter.Transform12(goiter.SliceElems(c.products), func(p *Product) (string, float64) {
        return p.Name, float64(p.Quantity) * p.Price
    })
}

func PrintNamesAges(cart *Cart) {
    // Checkout hides the internal details of the cart. So external code can only access the transformed data during iteration.
    for name, cost := range cart.Checkout() {
        fmt.Printf("The %s costs %.2f\n", name, cost)
    }
}
Example 4: Filtering
package example4

import (
    "fmt"
    "github.com/hsldymq/goiter"
)

// This example demonstrates the use of the goiter.Filter function to filter elements in an iterator.
func FilterDemo() {
    input := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    iterator := goiter.SliceElems(input).Filter(func(v int) bool {
        return v % 2 == 0
    }) 
    // This will print 2 4 6 8 10
    for each := range iterator {
        fmt.Printf("%d ", each)
    }
}

// This example demonstrates the use of the goiter.Distinct function to remove duplicate elements from an iterator.
func DistinctDemo() {
    input := []int{1, 2, 3, 3, 2, 1}
    // This will print 1 2 3
    for each := range goiter.Distinct(goiter.SliceElems(input)) {
        fmt.Printf("%d ", each)
    }
}
Example 5: Ordering
package example5

import (
	"fmt"
	"github.com/hsldymq/goiter"
)

// This example demonstrates how to use the goiter.Order function to sort elements in an iterator.
// Note: The goiter.Order series functions use additional memory to store intermediate results during sorting. Therefore, if the source iterator produces a large amount of data, use these functions with caution.
func Demo() {
    // This will print 1 2 3 4
    for each := range goiter.Order(goiter.Items(1, 4, 3, 2)) {
        fmt.Printf("%d ", each)
    }

    // pass true as the second argument to sort in descending order
    // So this will print 4 3 2 1
    for each := range goiter.Order(goiter.Items(1, 4, 3, 2), true) {
        fmt.Printf("%d ", each)
    }
}

List of goiter functions

Below are the functions provided by goiter.

As you can see, some functions are provided in two versions, such as Filter and Filter2, Take and Take2. These functions are respectively used for iterators of the iter.Seq or iter.Seq2 versions.

Additionally, some functions have the suffix V1 or V2 in their names. These functions are for iter.Seq2 iterators, with V1 applying operations to the first element of each 2-tuple in the iteration, and V2 applying operations to the second element.

The comments at the function definitions include simple examples to help you better understand how to use these functions.

transformation
  • PickV1
  • PickV2
  • Swap
  • Transform
  • Transform2
  • Transform12
  • Transform21
aggregation
  • Count
  • Count2
  • Reduce
  • Scan
sequence
  • Range
  • RangeStep
  • Counter
  • Sequence
  • Sequence2
  • Reverse
  • Reverse2
combining
  • Combine
  • Zip
  • ZipAs
  • Concat
  • Concat2
filtering
  • Filter
  • Filter2
  • OfType
  • Take
  • Take2
  • TakeLast
  • TakeLast2
  • Skip
  • Skip2
  • SkipLast
  • SkipLast2
  • Distinct
  • DistinctV1
  • DistinctV2
  • DistinctBy
  • Distinct2By
ordering
  • Order
  • OrderBy
  • Order2V1
  • Order2V2
  • Order2By
  • StableOrderBy
  • StableOrder2By
unrepeatable iterator
  • Once
  • Once2
  • FinishOnce
  • FinishOnce2
Creating iterators from sources
  • Items
  • Slice
  • SliceElems
  • SliceSource
  • SliceSourceElems
  • Map
  • MapVals
  • MapKeys
  • MapSource
  • MapSourceVals
  • MapSourceKeys
  • SeqSource
  • Seq2Source
  • Empty
  • Empty2

Method chaining

Many of the functions listed above return an iterator of type goiter.Iterator[T] (or goiter.Iterator2[T1, T2]).

They are iterators and also have methods that allow you to chain multiple operations together.

The following two methods of generating iterators are equivalent.

// Non-method chaining
iterator := goiter.Items(1, 2, 3, 4, 5, 6)
iterator = goiter.Filter(iterator, func(v int) bool {
    return v % 2 == 0
})

// Method chaining
iterator := goiter.Items(1, 2, 3, 4, 5, 6).Filter(func(v int) bool {
    return v % 2 == 0
})

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Count

func Count[TIter SeqX[T], T any](iterator TIter) int

Count counts the number of elements yielded by the input iterator.

func Count2

func Count2[TIter Seq2X[T1, T2], T1 any, T2 any](iterator TIter) int

Count2 counts the number of elements yielded by the input iterator.

func Reduce

func Reduce[TIter SeqX[T], TAcc any, T any](
	iterator TIter,
	init TAcc,
	folder func(TAcc, T) TAcc,
) TAcc

Reduce is basically Reduce function in functional programming. The following example uses Reduce to sum up the numbers from 1 to 10:

 sum := goiter.Reduce(goiter.Range(1, 10), 0, func(acc, v int) int {
     return acc + v
	})

Types

type Combined

type Combined[T1, T2 any] struct {
	V1 T1
	V2 T2
}

func Combiner

func Combiner[T1, T2 any](v1 T1, v2 T2) *Combined[T1, T2]

type GeneratorFunc

type GeneratorFunc[T any] func() (T, bool)

type GeneratorFunc2

type GeneratorFunc2[T1, T2 any] func() (T1, T2, bool)

type Iterator

type Iterator[T any] iter.Seq[T]

func Cache

func Cache[TIter SeqX[T], T any](it TIter) Iterator[T]

Cache returns an iterator that caches the values of the input iterator.

func Combine

func Combine[TIter Seq2X[T1, T2], T1, T2 any](iterator TIter) Iterator[*Combined[T1, T2]]

Combine returns an iterator that yields combined values, where each value contains the elements of the 2-Tuple provided by the input iterator.

func Concat

func Concat[TIter SeqX[T], T any](
	iterator TIter,
	more ...TIter,
) Iterator[T]

Concat returns an iterator that allows you to traverse multiple iterators in sequence. So if iterator1 yields 1 2 3 and iterator2 yields 4 5 6, then goiter.Concat(iterator1, iterator2) will yield 1 2 3 4 5 6.

func Counter

func Counter(startFrom int) Iterator[int]

Counter returns an iterator that yields a sequence of integers incrementing by 1.

func Distinct

func Distinct[TIter SeqX[T], T comparable](iterator TIter) Iterator[T]

Distinct returns an iterator that only yields the distinct values of the input iterator. For example:

if the input iterator yields 1 2 3 3 2 1, Distinct function will yield 1 2 3.

Note: if this function is used on iterators that has massive amount of data, it might consume a lot of memory.

func DistinctBy

func DistinctBy[TIter SeqX[T], T any, K comparable](
	iterator TIter,
	keySelector func(T) K,
) Iterator[T]

DistinctBy accepts a custom function to determine the deduplicate-key. Note: if this function is used on iterators that has massive amount of data, it might consume a lot of memory.

func Empty

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

Empty returns an empty iterator.

func Filter

func Filter[TIter SeqX[T], T any](
	iterator TIter,
	predicate func(T) bool,
) Iterator[T]

Filter returns an iterator that only yields the values of the input iterator that satisfy the predicate.

func FinishOnce

func FinishOnce[TIter SeqX[T], T any](iterator TIter) Iterator[T]

FinishOnce unlike Once function, it can be iterated over multiple times until all values have been yielded exactly once. This means you can break out of the iteration midway and then continue iterating from where you left off. You can also iterate over it concurrently; FinishOnce will ensure that all values are yielded exactly once. once all values have been yielded, it will not yield any more values. For example:

iterator := goiter.FinishOnce(goiter.Items(1, 2, 3, 4, 5, 6))   // we have this FinishOnce iterator that yields 1, 2, 3, 4, 5, 6

for v := range iterator {   // in this loop, it will print 1, 2, 3
    fmt.Printf("%d ", v)
    if v == 3 {
        break
    }
}

for v := range iterator {   // in this loop, it will print remaining values 4, 5, 6
    fmt.Printf("%d ", v)
}

for v := range iterator {   // and in this loop, it will not print anything, because all values have been yielded
    fmt.Printf("%d ", v)    // so this line won't be executed
}

func Items

func Items[T any](t ...T) Iterator[T]

Items returns an iterator that simply yields the input values. So goiter.Items[any](1, true, 1.5, "hello") will yield 1 true 1.5 "hello".

func MapKeys

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

MapKeys yields only keys of a map in arbitrary order. This function is basically equivalent to the maps.Keys function.

func MapSourceKeys

func MapSourceKeys[K comparable, V any](source SourceFunc[map[K]V]) Iterator[K]

MapSourceKeys is like MapKeys function, it serves similar purposes as SliceSource. See comments of SliceSource function for more details.

func MapSourceVals

func MapSourceVals[K comparable, V any](source SourceFunc[map[K]V]) Iterator[V]

MapSourceVals is like MapVals function, it serves similar purposes as SliceSource. See comments of SliceSource function for more details.

func MapVals

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

MapVals yields only values of a map in arbitrary order. This function is basically equivalent to the maps.Values function.

func OfType

func OfType[U any, TIter SeqX[T], T any](
	iterator TIter,
) Iterator[U]

OfType returns an iterator that only yields the values of the input iterator that are of the specified type. this is useful when you have an iterator that yields interfaces, and you want to filter them by their type. For example:

iterator := goiter.Items[any](1, "hello", true, 3, "world")     // iterator yields 1 "hello" true 3 "world"
newIterator := goiter.OfType[int](iterator)                     // after calling OfType, newIterator will only yield 1 3

func Once

func Once[TIter SeqX[T], T any](iterator TIter) Iterator[T]

Once returns an iterator that can only be iterated over once; It cannot be reused after the iteration is complete or after breaking out of the loop. On subsequent attempts, it will yield nothing. Similarly, you cannot iterate over it in multiple goroutines. If you do so, only one goroutine will produce values.

func Order

func Order[TIter SeqX[T], T cmp.Ordered](
	iterator TIter,
	desc ...bool,
) Iterator[T]

Order sorts the elements of the input iterator and returns a new iterator whose elements are arranged in ascending or descending order. If the second parameter is true, the elements are arranged in descending order. For example:

since iter.SliceElems([]int{2, 3, 1})) yields 2 3 1
then Order(iter.SliceElems([]int{2, 3, 1}))       will yield 1 2 3
and  Order(iter.SliceElems([]int{2, 3, 1}), true) will yield 3 2 1.

Note: if this function is used on iterators that has massive amount of data, it might consume a lot of memory.

func OrderBy

func OrderBy[TIter SeqX[T], T any](
	iterator TIter,
	cmp func(T, T) int,
) Iterator[T]

OrderBy accepts a comparison function and returns a new iterator that yields elements sorted by the comparison function. Note: if this function is used on iterators that has massive amount of data, it might consume a lot of memory.

func PickV1

func PickV1[TIter Seq2X[T1, T2], T1, T2 any](iterator TIter) Iterator[T1]

PickV1 returns an iterator that yields the first element of each 2-tuple provided by the input iterator. For example:

iterator := goiter.Slice([]string{"a", "b", "c"})       // iterator will yield (1, "a") (2, "b") (3, "c")
newIterator := goiter.PickV1(iterator)                  // after calling PickV1, newIterator will yield 1 2 3

func PickV2

func PickV2[TIter Seq2X[T1, T2], T1, T2 any](iterator TIter) Iterator[T2]

PickV2 returns an iterator that yields the second element of each 2-tuple provided by the input iterator. For example:

iterator := goiter.Slice([]string{"a", "b", "c"})       // iterator will yield (1, "a") (2, "b") (3, "c")
newIterator := goiter.PickV2(iterator)                  // after calling PickV2, newIterator will yield "a" "b" "c"

func Range

func Range[T TInt](start, end T) Iterator[T]

Range returns an iterator that yields a sequence of integers forward or backward from start to end, incrementing/decrementing by 1. to be specific, the second parameter "end" is inclusive. for example:

goiter.Range(1, 5) // will yield 1, 2, 3, 4, 5
goiter.Range(3, -3) // will yield 3, 2, 1, 0, -1, -2, -3

func RangeStep

func RangeStep[T TInt, S TInt](start, end T, stepSize S) Iterator[T]

RangeStep extends the ability to Range function, allowing iteration from any integer and stepping forward or backward in any step. It is similar to Python's range function, but with some differences:

  1. the second parameter "end" is inclusive, rather than exclusive in Python's range function.
  2. stepSize does not accept negative numbers. Whether iterating in increasing or decreasing order, stepSize must be positive, so you don't need to consider adjusting the sign of step according to the direction of iteration, you can consider it as the absolute value of the step parameter of Python range function.
  3. Providing a value less than or equal to 0 for stepSize will not return an error, it simply doesn't yield any values.

func Reverse

func Reverse[TIter SeqX[T], T any](iterator TIter) Iterator[T]

Reverse returns an iterator that yields the values of the input iterator in reverse order. So if the input iterator yields "a" "b" "c", then goiter.Reverse(iterator) will yield "c" "b" "a".

be careful, if this function is used on iterators that has massive amount of data, it might consume a lot of memory.

func Scan

func Scan[TIter SeqX[T], TAcc any, T any](
	iterator TIter,
	init TAcc,
	folder func(TAcc, T) TAcc,
) Iterator[TAcc]

Scan is similar to Reduce function, but it returns an iterator that will yield the reduced value of each round. So, the following code will create an iterator that yields 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, where each value is the sum of numbers from 1 to the current number.

 iterator := goiter.Scan(goiter.Range(1, 10), 0, func(acc, v int) int {
     return acc + v
	})

func SeqSource

func SeqSource[TIter SeqX[T], T any](source SourceFunc[TIter]) Iterator[T]

SeqSource serves similar purposes as SliceSource, the difference is that the SourceFunc returns an iter.Seq-like iterator. See comments of SliceSource function for more details.

func Sequence

func Sequence[T any](generator func() (T, bool)) Iterator[T]

Sequence takes a generator function and returns an iterator that yields the values generated by the generator. This is a general sequence generator function For example, you can use it to generate the Fibonacci sequence like this:

genFib := func(n int) goiter.GeneratorFunc[int] {
	a, b := 0, 1
	return func() (int, bool) {
		if n <= 0 {
			return 0, false
		}
		n--
		a, b = b, a+b
		return a, true
	}
}
// this will print first 5 Fibonacci numbers: 1 1 2 3 5
for v := range goiter.Sequence(genFib(5)) {
	fmt.Printf("%d ", v)
}

func Skip

func Skip[TIter SeqX[T], T any](
	iterator TIter,
	n int,
) Iterator[T]

Skip returns an iterator that suppress the first n values of the input iterator and yields the rest. If the input iterator has less than n values, it will yield nothing.

So if an iterator yields 1 2 3 4 5, goiter.Skip(iterator, 3) will yield 4 5. And if an iterator yields 1 2, goiter.Skip(iterator, 3) will yield nothing.

func SkipLast

func SkipLast[TIter SeqX[T], T any](
	iterator TIter,
	n int,
) Iterator[T]

SkipLast returns an iterator that suppress the last n values of the input iterator and yields the rest. If the input iterator has less than n values, it will yield nothing.

So if an iterator yields 1 2 3 4 5, goiter.SkipLast(iterator, 3) will yield 1 2. And if an iterator yields 1 2, goiter.SkipLast(iterator, 3) will yield nothing.

func SliceElems

func SliceElems[S ~[]T, T any](s S, backward ...bool) Iterator[T]

SliceElems is like the Slice function, but it only yields the elements of the slice.

func SliceSourceElems

func SliceSourceElems[S ~[]T, T any](source SourceFunc[S], backward ...bool) Iterator[T]

SliceSourceElems is like SliceElems function, it serves similar purposes as SliceSource. see comments of SliceSource function for more details.

func StableOrderBy

func StableOrderBy[TIter SeqX[T], T any](
	iterator TIter,
	cmp func(T, T) int,
) Iterator[T]

StableOrderBy is like OrderBy, but it uses a stable sort algorithm. Note: if this function is used on iterators that has massive amount of data, it might consume a lot of memory.

func Take

func Take[TIter SeqX[T], T any](
	iterator TIter,
	n int,
) Iterator[T]

Take returns an iterator that yields the first n values of the input iterator. If the input iterator has less than n values, it will yield all the values.

So if an iterator yields 1 2 3 4 5, goiter.Take(iterator, 3) will yield 1 2 3. And if an iterator yields 1 2, goiter.Take(iterator, 3) will yield 1 2.

func TakeLast

func TakeLast[TIter SeqX[T], T any](
	iterator TIter,
	n int,
) Iterator[T]

TakeLast returns an iterator that yields the last n values of the input iterator. If the input iterator has less than n values, it will yield all the values.

So if an iterator yields 1 2 3 4 5, goiter.Take(iterator, 3) will yield 3 4 5. And if an iterator yields 1 2, goiter.Take(iterator, 3) will yield 1 2.

func Transform

func Transform[TIter SeqX[T], TOut, T any](
	iterator TIter,
	transformer func(T) TOut,
) Iterator[TOut]

Transform returns an iterator, it yields new values by applying the transformer function to each value provided by the input iterator. For example:

iterator := goiter.SliceElems([]int{1, 2, 3})               // iterator will yield 1 2 3
newIterator := goiter.Transform(iterator, strconv.Itoa)     // after calling Transform, newIterator will yield "1" "2" "3"

func Transform21

func Transform21[TIter Seq2X[T1, T2], TOut, T1, T2 any](
	iterator TIter,
	transformer func(T1, T2) TOut,
) Iterator[TOut]

Transform21 is similar to Transform12, but it is reversed, it transforms each 2-tuple value from the input iterator to single-values.

func ZipAs

func ZipAs[TIter1 SeqX[T1], TIter2 SeqX[T2], TOut, T1, T2 any](
	iterator1 TIter1,
	iterator2 TIter2,
	transformer func(*Zipped[T1, T2]) TOut,
	exhaust bool,
) Iterator[TOut]

ZipAs is a more general version of Zip. if exhaust parameter is true, the resulting iterator will not stop until both input iterators stop, and Zipped.OK1 and Zipped.OK2 will be false when the corresponding iterator stops.

func (Iterator[T]) Cache

func (it Iterator[T]) Cache() Iterator[T]

func (Iterator[T]) Concat

func (it Iterator[T]) Concat(its ...Iterator[T]) Iterator[T]

func (Iterator[T]) Count

func (it Iterator[T]) Count() int

func (Iterator[T]) Filter

func (it Iterator[T]) Filter(predicate func(T) bool) Iterator[T]

func (Iterator[T]) FinishOnce

func (it Iterator[T]) FinishOnce() Iterator[T]

func (Iterator[T]) Once

func (it Iterator[T]) Once() Iterator[T]

func (Iterator[T]) OrderBy

func (it Iterator[T]) OrderBy(cmp func(T, T) int) Iterator[T]

func (Iterator[T]) Reverse

func (it Iterator[T]) Reverse() Iterator[T]

func (Iterator[T]) Seq

func (it Iterator[T]) Seq() iter.Seq[T]

func (Iterator[T]) Skip

func (it Iterator[T]) Skip(n int) Iterator[T]

func (Iterator[T]) SkipLast

func (it Iterator[T]) SkipLast(n int) Iterator[T]

func (Iterator[T]) StableOrderBy

func (it Iterator[T]) StableOrderBy(cmp func(T, T) int) Iterator[T]

func (Iterator[T]) Take

func (it Iterator[T]) Take(n int) Iterator[T]

func (Iterator[T]) TakeLast

func (it Iterator[T]) TakeLast(n int) Iterator[T]

func (Iterator[T]) Through

func (it Iterator[T]) Through(f func(T) T) Iterator[T]

func (Iterator[T]) WithCounter

func (it Iterator[T]) WithCounter(startFrom int) Iterator2[int, T]

type Iterator2

type Iterator2[T1, T2 any] iter.Seq2[T1, T2]

func Cache2

func Cache2[TIter Seq2X[T1, T2], T1 any, T2 any](it TIter) Iterator2[T1, T2]

Cache2 is iter.Seq2 version of Cache.

func Concat2

func Concat2[TIter Seq2X[T1, T2], T1 any, T2 any](
	iterator TIter,
	more ...TIter,
) Iterator2[T1, T2]

Concat2 is the iter.Seq2 version of Concat function.

func Distinct2By

func Distinct2By[TIter Seq2X[T1, T2], T1 any, T2 any, K comparable](
	iterator TIter,
	keySelector func(T1, T2) K,
) Iterator2[T1, T2]

Distinct2By is the iter.Seq2 version of DistinctBy function. Note: if this function is used on iterators that has massive amount of data, it might consume a lot of memory.

func DistinctV1

func DistinctV1[TIter Seq2X[T1, T2], T1 comparable, T2 any](iterator TIter) Iterator2[T1, T2]

DistinctV1 returns an iterator that deduplicate the 2-tuples provided by the input iterator according to the first element. For example:

if the input iterator yields ("john", 20) ("anne", 21) ("john", 22)
DistinctV1 function will yield ("john", 20) ("anne", 21) because ("john", 22) has the same key as ("john", 20).

Note: if this function is used on iterators that has massive amount of data, it might consume a lot of memory.

func DistinctV2

func DistinctV2[TIter Seq2X[T1, T2], T1 any, T2 comparable](iterator TIter) Iterator2[T1, T2]

DistinctV2 is similar to DistinctV1 function, but it deduplicates by the second element of the 2-tuple. Note: if this function is used on iterators that has massive amount of data, it might consume a lot of memory.

func Empty2

func Empty2[T1 any, T2 any]() Iterator2[T1, T2]

Empty2 is the iter.Seq2 version of Empty

func Filter2

func Filter2[TIter Seq2X[T1, T2], T1 any, T2 any](
	iterator TIter,
	predicate func(T1, T2) bool,
) Iterator2[T1, T2]

Filter2 is the iter.Seq2 version of Filter function.

func FinishOnce2

func FinishOnce2[TIter Seq2X[T1, T2], T1, T2 any](iterator TIter) Iterator2[T1, T2]

FinishOnce2 is the iter.Seq2 version of FinishOnce function.

func Map

func Map[K comparable, V any](m map[K]V) Iterator2[K, V]

Map returns an iterator that allows you to traverse a map. This function is basically equivalent to the maps.All function.

func MapSource

func MapSource[K comparable, V any](source SourceFunc[map[K]V]) Iterator2[K, V]

MapSource is like Map function, it serves similar purposes as SliceSource. See comments of SliceSource function for more details.

func Once2

func Once2[TIter Seq2X[T1, T2], T1, T2 any](iterator TIter) Iterator2[T1, T2]

Once2 is the iter.Seq2 version of Once function.

func Order2By

func Order2By[TIter Seq2X[T1, T2], T1, T2 any](
	iterator TIter,
	cmp func(*Combined[T1, T2], *Combined[T1, T2]) int,
) Iterator2[T1, T2]

Order2By is the iter.Seq2 version of OrderBy. Note: if this function is used on iterators that has massive amount of data, it might consume a lot of memory.

func Order2V1

func Order2V1[TIter Seq2X[T1, T2], T1 cmp.Ordered, T2 any](
	iterator TIter,
	desc ...bool,
) Iterator2[T1, T2]

Order2V1 sorts the 2-tuples of the input iterator by first element and returns a new iterator whose elements are arranged in ascending or descending order. If the second parameter is true, the tuples are arranged in descending order. For example:

since iter.Map(map[string]int{"bob":3, "eve":2, "alice":1}) yields the 2-tuples in arbitrary order
then Order2V1(iter.Map(map[string]int{"bob":3, "eve":2, "alice":1}))       will yield (alice, 1) (bob 3) (eve 2)
and  Order2V1(iter.Map(map[string]int{"bob":3, "eve":2, "alice":1}), true) will yield (eve 2) (bob 3) (alice, 1).

Note: if this function is used on iterators that has massive amount of data, it might consume a lot of memory.

func Order2V2

func Order2V2[TIter Seq2X[T1, T2], T1 any, T2 cmp.Ordered](
	iterator TIter,
	desc ...bool,
) Iterator2[T1, T2]

Order2V2 is like Order2V1, but it sorts by the second element of the 2-tuples. be careful, if this function is used on iterators that has massive amount of data, it might consume a lot of memory.

func Reverse2

func Reverse2[TIter Seq2X[T1, T2], T1, T2 any](iterator TIter) Iterator2[T1, T2]

Reverse2 is the iter.Seq2 version of Reverse function. be careful, if this function is used on iterators that has massive amount of data, it might consume a lot of memory.

func Seq2Source

func Seq2Source[TIter Seq2X[T1, T2], T1, T2 any](source SourceFunc[TIter]) Iterator2[T1, T2]

Seq2Source serves similar purposes as SliceSource. See comments of SliceSource function for more details.

func Sequence2

func Sequence2[T1, T2 any](generator func() (T1, T2, bool)) Iterator2[T1, T2]

Sequence2 is the iter.Seq2 version of Sequence function.

func Skip2

func Skip2[TIter Seq2X[T1, T2], T1, T2 any](
	iterator TIter,
	n int,
) Iterator2[T1, T2]

Skip2 is the iter.Seq2 version of Skip function.

func SkipLast2

func SkipLast2[TIter Seq2X[T1, T2], T1, T2 any](
	iterator TIter,
	n int,
) Iterator2[T1, T2]

SkipLast2 is the iter.Seq2 version of SkipLast function.

func Slice

func Slice[S ~[]T, T any](s S, backward ...bool) Iterator2[int, T]

Slice returns an iterator that allows you to traverse a slice in a forward or reverse direction. So this function combines the functionalities of slices.Values and slices.Backward.

func SliceSource

func SliceSource[S ~[]T, T any](source SourceFunc[S], backward ...bool) Iterator2[int, T]

SliceSource is like the Slice function, but the slice is taken from the input SourceFunc. You might use this function in scenarios like this: When a slice is encapsulated within a struct, it offers the capability to traverse elements by exposing an iterator. However, there might come a time when the structure replaces the original slice with a new one. When the already exposed iterator is traversed again, we hope it traverses the new slice instead of the old one. Therefore, by providing a SourceFunc, the moment of obtaining the slice is delayed until the iterator is traversed.

func StableOrder2By

func StableOrder2By[TIter Seq2X[T1, T2], T1, T2 any](
	iterator TIter,
	cmp func(*Combined[T1, T2], *Combined[T1, T2]) int,
) Iterator2[T1, T2]

StableOrder2By is like Order2By, but it uses a stable sort algorithm. Note: if this function is used on iterators that has massive amount of data, it might consume a lot of memory.

func Swap

func Swap[TIter Seq2X[T1, T2], T1, T2 any](iterator TIter) Iterator2[T2, T1]

Swap returns an iterator that yields new 2-tuples by swapping the positions of the elements within each 2-Tuple provided by the input iterator. For example:

iterator := goiter.Slice([]string{"a", "b", "c"})       // iterator will yield (1, "a") (2, "b") (3, "c")
newIterator := goiter.Swap(iterator)                    // after calling Swap, newIterator will yield ("a", 1) ("b", 2) ("c", 3)

func Take2

func Take2[TIter Seq2X[T1, T2], T1, T2 any](
	iterator TIter,
	n int,
) Iterator2[T1, T2]

Take2 is the iter.Seq2 version of Take function.

func TakeLast2

func TakeLast2[TIter Seq2X[T1, T2], T1, T2 any](
	iterator TIter,
	n int,
) Iterator2[T1, T2]

TakeLast2 is the iter.Seq2 version of TakeLast function.

func Transform12

func Transform12[TIter SeqX[T], OutT1, OutT2, T any](
	iterator TIter,
	transformer func(T) (OutT1, OutT2),
) Iterator2[OutT1, OutT2]

Transform12 is similar to Transform, but it transforms each value from the input iterator to 2-tuple values. For example:

iterator := goiter.SliceElems([]string{"hello", "golang"})               // iterator will yield "hello" "golang"
newIterator := goiter.Transform12(iterator, func(s string) (string, int) {
    return s, len(s)
})     // after calling Transform12, newIterator will yield ("hello", 5) ("golang", 6)

func Transform2

func Transform2[TIter Seq2X[T1, T2], TOut1, TOut2, T1, T2 any](
	iterator TIter,
	transformer func(T1, T2) (TOut1, TOut2),
) Iterator2[TOut1, TOut2]

Transform2 is the iter.Seq2 version of Transform function, it transforms each 2-tuple values from the input iterator and yields the transformed 2-tuple values.

func Zip

func Zip[TIter1 SeqX[T1], TIter2 SeqX[T2], T1, T2 any](
	iterator1 TIter1,
	iterator2 TIter2,
) Iterator2[T1, T2]

Zip is like python's zip function, it takes two iterators and returns an iterator that yields 2-tuples, where the first element of the 2-tuple is from the first iterator, and the second element is from the second iterator when two iterators have different lengths, the resulting iterator will stop when the shorter one stops. for example:

it1 yields  1   2   3   4   5
it2 yields "a" "b" "c"
Zip(it1, it2) will yield (1, "a") (2, "b") (3, "c")

func (Iterator2[T1, T2]) Cache

func (it Iterator2[T1, T2]) Cache() Iterator2[T1, T2]

func (Iterator2[T1, T2]) Concat

func (it Iterator2[T1, T2]) Concat(its ...Iterator2[T1, T2]) Iterator2[T1, T2]

func (Iterator2[T1, T2]) Count

func (it Iterator2[T1, T2]) Count() int

func (Iterator2[T1, T2]) Filter

func (it Iterator2[T1, T2]) Filter(cmp func(T1, T2) bool) Iterator2[T1, T2]

func (Iterator2[T1, T2]) FinishOnce

func (it Iterator2[T1, T2]) FinishOnce() Iterator2[T1, T2]

func (Iterator2[T1, T2]) Once

func (it Iterator2[T1, T2]) Once() Iterator2[T1, T2]

func (Iterator2[T1, T2]) OrderBy

func (it Iterator2[T1, T2]) OrderBy(cmp func(*Combined[T1, T2], *Combined[T1, T2]) int) Iterator2[T1, T2]

func (Iterator2[T1, T2]) PickV1

func (it Iterator2[T1, T2]) PickV1() Iterator[T1]

PickV1 returns an iterator that yields the first value of each pair.

func (Iterator2[T1, T2]) PickV2

func (it Iterator2[T1, T2]) PickV2() Iterator[T2]

PickV2 returns an iterator that yields the second value of each pair.

func (Iterator2[T1, T2]) Reverse

func (it Iterator2[T1, T2]) Reverse() Iterator2[T1, T2]

func (Iterator2[T1, T2]) Seq

func (it Iterator2[T1, T2]) Seq() iter.Seq2[T1, T2]

func (Iterator2[T1, T2]) Skip

func (it Iterator2[T1, T2]) Skip(n int) Iterator2[T1, T2]

func (Iterator2[T1, T2]) SkipLast

func (it Iterator2[T1, T2]) SkipLast(n int) Iterator2[T1, T2]

func (Iterator2[T1, T2]) StableOrderBy

func (it Iterator2[T1, T2]) StableOrderBy(cmp func(*Combined[T1, T2], *Combined[T1, T2]) int) Iterator2[T1, T2]

func (Iterator2[T1, T2]) Take

func (it Iterator2[T1, T2]) Take(n int) Iterator2[T1, T2]

func (Iterator2[T1, T2]) TakeLast

func (it Iterator2[T1, T2]) TakeLast(n int) Iterator2[T1, T2]

func (Iterator2[T1, T2]) Through

func (it Iterator2[T1, T2]) Through(f func(T1, T2) (T1, T2)) Iterator2[T1, T2]

type Seq2X

type Seq2X[T1, T2 any] interface {
	~func(yield func(T1, T2) bool)
}

type SeqX

type SeqX[T any] interface {
	~func(yield func(T) bool)
}

type SourceFunc

type SourceFunc[T any] func() T

SourceFunc delegates data retrieval from elsewhere.

type TInt

type TInt interface {
	~int | ~int8 | ~int16 | ~int32 | ~int64 |
		~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64
}

type Zipped

type Zipped[T1, T2 any] struct {
	V1  T1
	OK1 bool
	V2  T2
	OK2 bool
}

Jump to

Keyboard shortcuts

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