Documentation
¶
Overview ¶
Package itertools provides a powerful and flexible generic iterator system for Go. It enables functional-style iteration, transformation, and aggregation of collections with support for lazy evaluation and composable operations.
The library is inspired by iterator protocols found in Python and Rust, adapted for Go's type system and idioms using Go 1.23+ generics and iter.Seq.
Index ¶
- func Fold[V any, T any](it *Iterator[V], transform func(T, V) T, initial T) T
- func Product[V any, T Productable](it *Iterator[V], transform func(V) T, one T) T
- func Sum[V any, T cmp.Ordered](it *Iterator[V], transform func(V) T, zero T) T
- type CSVRow
- type Iterator
- func CartesianProduct[A, B any](it1 *Iterator[A], it2 *Iterator[B]) ...
- func ChunkList[V any](it *Iterator[V], size int) []*Iterator[V]
- func ChunkSlice[V any](it *Iterator[V], size int) *Iterator[[]V]
- func Chunks[V any](it *Iterator[V], size int) *Iterator[*Iterator[V]]
- func Flatten[V any](its ...*Iterator[V]) *Iterator[V]
- func FromCSV(r *csv.Reader) *Iterator[[]string]
- func FromCSVWithContext(ctx context.Context, r *csv.Reader) *Iterator[[]string]
- func FromCSVWithHeaders(r *csv.Reader) (*Iterator[CSVRow], []string, error)
- func FromCSVWithHeadersContext(ctx context.Context, r *csv.Reader) (*Iterator[CSVRow], []string, error)
- func FromChannel[V any](ch <-chan V) *Iterator[V]
- func FromChannelWithContext[V any](ctx context.Context, ch <-chan V) *Iterator[V]
- func FromFunc[V any](fn func() (V, bool)) *Iterator[V]
- func FromFuncWithContext[V any](ctx context.Context, fn func() (V, bool)) *Iterator[V]
- func FromReader(r io.Reader) *Iterator[string]
- func FromReaderWithContext(ctx context.Context, r io.Reader) *Iterator[string]
- func Generate[V any](fn func() V) *Iterator[V]
- func GenerateWithContext[V any](ctx context.Context, fn func() V) *Iterator[V]
- func NewIterator[V any](v ...V) *Iterator[V]
- func Range(start, end int) *Iterator[int]
- func RangeStep(start, end, step int) *Iterator[int]
- func Repeat[V any](v V, n int) *Iterator[V]
- func ToIter[V any](slice []V) *Iterator[V]
- func Zip[A, B any](it1 *Iterator[A], it2 *Iterator[B]) ...
- func Zip2[A, B any](it1 *Iterator[A], it2 *Iterator[B], fill struct{ ... }) ...
- func (it *Iterator[V]) All(predicate func(V) bool) bool
- func (it *Iterator[V]) Any(predicate func(V) bool) bool
- func (it *Iterator[V]) AssertEq(expected []V, predicate func(V, V) bool) bool
- func (it *Iterator[V]) Chain(other *Iterator[V]) *Iterator[V]
- func (it *Iterator[V]) Collect() []V
- func (it *Iterator[V]) Compact() *Iterator[V]
- func (it *Iterator[V]) CompactWith(zero V) *Iterator[V]
- func (it *Iterator[V]) Count() int
- func (it *Iterator[V]) Current() V
- func (it *Iterator[V]) Cycle() *Iterator[V]
- func (it *Iterator[V]) Difference(other *Iterator[V], keyFunc func(V) any) *Iterator[V]
- func (it *Iterator[V]) Drop(n int) *Iterator[V]
- func (it *Iterator[V]) DropWhile(predicate func(V) bool) *Iterator[V]
- func (it *Iterator[V]) Each(f func(V))
- func (it *Iterator[V]) Filter(predicate func(V) bool) *Iterator[V]
- func (it *Iterator[V]) Find(predicate func(V) bool) (V, bool)
- func (it *Iterator[V]) First() V
- func (it *Iterator[V]) FirstOr(defaultValue V) V
- func (it *Iterator[V]) GroupBy(keyFunc func(V) string) map[string][]V
- func (it *Iterator[V]) Index(predicate func(V) bool) int
- func (it *Iterator[V]) Intersection(other *Iterator[V], keyFunc func(V) any) *Iterator[V]
- func (it *Iterator[V]) IsSorted(less func(a, b V) bool) bool
- func (it *Iterator[V]) Last() V
- func (it *Iterator[V]) LastIndex(predicate func(V) bool) int
- func (it *Iterator[V]) LastOr(defaultValue V) V
- func (it *Iterator[V]) Map(f func(V) V) *Iterator[V]
- func (it *Iterator[V]) Max(less func(a, b V) bool) (V, bool)
- func (it *Iterator[V]) Min(less func(a, b V) bool) (V, bool)
- func (it *Iterator[V]) Next() bool
- func (it *Iterator[V]) Nth(n int) V
- func (it *Iterator[V]) NthOr(n int, defaultValue V) V
- func (it *Iterator[V]) Partition(predicate func(V) bool) (matched *Iterator[V], unmatched *Iterator[V])
- func (it *Iterator[V]) Replace(predicate func(V) bool, replacement V) *Iterator[V]
- func (it *Iterator[V]) ReplaceAll(replacement V) *Iterator[V]
- func (it *Iterator[V]) Reverse() *Iterator[V]
- func (it *Iterator[V]) Shuffle() *Iterator[V]
- func (it *Iterator[V]) Sort(less func(a, b V) bool) *Iterator[V]
- func (it *Iterator[V]) StepBy(n int) *Iterator[V]
- func (it *Iterator[V]) String() string
- func (it *Iterator[V]) Take(n int) *Iterator[V]
- func (it *Iterator[V]) TakeWhile(predicate func(V) bool) *Iterator[V]
- func (it *Iterator[V]) ToLower() *Iterator[V]
- func (it *Iterator[V]) ToUpper() *Iterator[V]
- func (it *Iterator[V]) TrimSpace() *Iterator[V]
- func (it *Iterator[V]) Union(other *Iterator[V], keyFunc func(V) any) *Iterator[V]
- func (it *Iterator[V]) Unique(keyFunc func(V) any) *Iterator[V]
- type Productable
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Fold ¶
Fold accumulates the elements of the iterator using a binary operation. Also known as reduce or aggregate in other languages.
The transform function takes an accumulator and the next value, returning the new accumulator value.
Example:
iter := itertools.ToIter([]int{1, 2, 3, 4, 5})
sum := itertools.Fold(iter, func(acc, v int) int { return acc + v }, 0)
// sum is 15
func Product ¶
func Product[V any, T Productable](it *Iterator[V], transform func(V) T, one T) T
Product multiplies all elements of the iterator after applying the transform function. The one parameter specifies the multiplicative identity for the result type.
Example:
iter := itertools.ToIter([]int{1, 2, 3, 4, 5})
product := itertools.Product(iter, func(v int) int { return v }, 1)
// product is 120
func Sum ¶
Sum adds all elements of the iterator after applying the transform function. The zero parameter specifies the additive identity for the result type.
Example:
iter := itertools.ToIter([]int{1, 2, 3, 4, 5})
sum := itertools.Sum(iter, func(v int) int { return v }, 0)
// sum is 15
// Sum of squares
iter2 := itertools.ToIter([]int{1, 2, 3})
sumSquares := itertools.Sum(iter2, func(v int) int { return v * v }, 0)
// sumSquares is 14
Types ¶
type CSVRow ¶ added in v1.1.0
CSVRow represents a parsed CSV row with helper methods
type Iterator ¶
type Iterator[V any] struct { // contains filtered or unexported fields }
Iterator is a generic iterator that can iterate over any type of sequence. It supports both functional-style operations (via the seq field) and imperative-style iteration (via Next/Current methods).
Iterator provides lazy evaluation - operations are only performed when elements are consumed. This allows efficient processing of large or infinite sequences.
Example:
iter := itertools.ToIter([]int{1, 2, 3, 4, 5})
result := iter.
Filter(func(x int) bool { return x%2 == 0 }).
Map(func(x int) int { return x * x }).
Collect()
// result is []int{4, 16}
func CartesianProduct ¶
CartesianProduct returns an iterator of all pairs of elements from two iterators. Note: The second iterator (it2) is fully collected into memory to enable multiple iterations over it for each element in it1. Use with caution for large datasets.
Example:
iter1 := ToIter([]int{1, 2})
iter2 := ToIter([]string{"a", "b"})
product := CartesianProduct(iter1, iter2).Collect()
// Result: [{1, "a"}, {1, "b"}, {2, "a"}, {2, "b"}]
func ChunkList ¶
ChunkList returns a slice of iterators, each containing up to `size` elements. This is a convenience function that collects Chunks into a slice.
Example:
iter := itertools.ToIter([]int{1, 2, 3, 4, 5, 6})
chunks := itertools.ChunkList(iter, 2)
// chunks is []*Iterator with 3 iterators containing [1,2], [3,4], [5,6]
func ChunkSlice ¶
ChunkSlice returns an iterator that yields slices of up to `size` elements. The last chunk may contain fewer elements if the total is not divisible by size.
Each chunk is a separate slice - modifications won't affect the original data.
Example:
iter := itertools.ToIter([]int{1, 2, 3, 4, 5, 6, 7})
chunks := itertools.ChunkSlice(iter, 3).Collect()
// chunks is [][]int{{1, 2, 3}, {4, 5, 6}, {7}}
func Chunks ¶
Chunks returns an iterator that yields iterators, each containing up to `size` elements. The last chunk may contain fewer elements if the total is not divisible by size.
Unlike ChunkSlice, this returns iterators instead of slices.
Example:
iter := itertools.ToIter([]int{1, 2, 3, 4, 5})
chunks := itertools.Chunks(iter, 2)
for chunks.Next() {
chunk := chunks.Current()
fmt.Println(chunk.Collect())
}
// Output: [1 2]
// [3 4]
// [5]
func Flatten ¶
Flatten concatenates multiple iterators into a single iterator. Elements are yielded in order: all elements from the first iterator, then all from the second, and so on.
Properly handles early termination - stops immediately when yield returns false.
Example:
iter1 := itertools.ToIter([]int{1, 2, 3})
iter2 := itertools.ToIter([]int{4, 5, 6})
iter3 := itertools.ToIter([]int{7, 8, 9})
flattened := itertools.Flatten(iter1, iter2, iter3).Collect()
// flattened is []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
func FromCSV ¶ added in v1.1.0
FromCSV creates a lazy Iterator that reads records from a CSV reader. Each element is a []string representing one CSV row. This is useful for processing large CSV files without loading them entirely into memory.
Example:
file, _ := os.Open("large_data.csv")
defer file.Close()
iter := itertools.FromCSV(csv.NewReader(file))
records := iter.Filter(func(row []string) bool {
return len(row) > 0 && row[0] != ""
}).Take(100).Collect()
func FromCSVWithContext ¶ added in v1.1.0
FromCSVWithContext creates a lazy Iterator from a CSV reader with context support. The iterator will stop when either the CSV is exhausted or the context is cancelled.
Example:
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
file, _ := os.Open("huge_data.csv")
defer file.Close()
iter := itertools.FromCSVWithContext(ctx, csv.NewReader(file))
records := iter.Collect()
func FromCSVWithHeaders ¶ added in v1.1.0
FromCSVWithHeaders creates a lazy Iterator that reads CSV records with header support. The first row is treated as headers and subsequent rows are wrapped in CSVRow for easier access. Returns the iterator and the header row.
Example:
file, _ := os.Open("data.csv")
defer file.Close()
iter, headers := itertools.FromCSVWithHeaders(csv.NewReader(file))
records := iter.Filter(func(row CSVRow) bool {
age := row.GetByHeader(headers, "age")
return age != "" && age > "30"
}).Collect()
func FromCSVWithHeadersContext ¶ added in v1.1.0
func FromCSVWithHeadersContext(ctx context.Context, r *csv.Reader) (*Iterator[CSVRow], []string, error)
FromCSVWithHeadersContext creates a lazy Iterator from CSV with headers and context support.
Example:
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute)
defer cancel()
file, _ := os.Open("large.csv")
defer file.Close()
iter, headers, _ := itertools.FromCSVWithHeadersContext(ctx, csv.NewReader(file))
func FromChannel ¶ added in v1.1.0
FromChannel creates a lazy Iterator from a channel. The iterator will consume elements from the channel until it's closed. This is useful for concurrent producer-consumer patterns.
Example:
ch := make(chan int)
go func() {
for i := 0; i < 10; i++ {
ch <- i
}
close(ch)
}()
iter := itertools.FromChannel(ch)
result := iter.Filter(func(x int) bool { return x%2 == 0 }).Collect()
func FromChannelWithContext ¶ added in v1.1.0
FromChannelWithContext creates a lazy Iterator from a channel with context support. The iterator will stop when either the channel is closed or the context is cancelled.
Example:
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() ch := make(chan int) iter := itertools.FromChannelWithContext(ctx, ch)
func FromFunc ¶ added in v1.1.0
FromFunc creates a lazy Iterator from a generator function. The function is called repeatedly until it returns false. This is useful for generating infinite sequences or custom data sources.
Example:
// Fibonacci sequence
iter := itertools.FromFunc(func() (int, bool) {
a, b := 0, 1
return func() (int, bool) {
result := a
a, b = b, a+b
return result, true
}
}())
first10 := iter.Take(10).Collect()
func FromFuncWithContext ¶ added in v1.1.0
FromFuncWithContext creates a lazy Iterator from a generator function with context support. The iterator will stop when either the function returns false or the context is cancelled.
Example:
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
iter := itertools.FromFuncWithContext(ctx, func() (int, bool) {
return rand.Int(), true
})
result := iter.Take(100).Collect()
func FromReader ¶ added in v1.1.0
FromReader creates a lazy Iterator that reads lines from an io.Reader. Each element is a line from the reader (without the newline character). This is useful for processing large files without loading them entirely into memory.
Example:
file, _ := os.Open("large_file.txt")
defer file.Close()
iter := itertools.FromReader(file)
count := iter.Filter(func(line string) bool {
return strings.Contains(line, "ERROR")
}).Count()
func FromReaderWithContext ¶ added in v1.1.0
FromReaderWithContext creates a lazy Iterator from an io.Reader with context support. The iterator will stop when either the reader is exhausted or the context is cancelled.
Example:
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
file, _ := os.Open("large_file.txt")
defer file.Close()
iter := itertools.FromReaderWithContext(ctx, file)
func Generate ¶ added in v1.1.0
Generate creates an infinite Iterator by repeatedly calling a generator function. Use Take() or TakeWhile() to limit the output.
Example:
counter := 0
iter := itertools.Generate(func() int {
counter++
return counter
})
first5 := iter.Take(5).Collect() // [1, 2, 3, 4, 5]
func GenerateWithContext ¶ added in v1.1.0
GenerateWithContext creates an infinite Iterator with context support.
Example:
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
iter := itertools.GenerateWithContext(ctx, func() int {
return rand.Int()
})
result := iter.Take(1000).Collect()
func NewIterator ¶
NewIterator creates a new iterator from a variadic list of values.
Example:
iter := itertools.NewIterator(1, 2, 3, 4, 5)
result := iter.Collect()
// result is []int{1, 2, 3, 4, 5}
func Range ¶ added in v1.1.0
Range creates an Iterator that yields integers from start (inclusive) to end (exclusive). This is useful for generating sequences of numbers.
Example:
iter := itertools.Range(0, 10) // yields 0, 1, 2, ..., 9
squares := iter.Map(func(x int) int { return x * x }).Collect()
func RangeStep ¶ added in v1.1.0
RangeStep creates an Iterator that yields integers from start to end with a given step.
Example:
iter := itertools.RangeStep(0, 10, 2) // yields 0, 2, 4, 6, 8 result := iter.Collect()
func Repeat ¶
Repeat creates an iterator that yields the same value n times.
Example:
iter := itertools.Repeat(42, 5)
result := iter.Collect()
// result is []int{42, 42, 42, 42, 42}
func ToIter ¶
ToIter creates an Iterator from a slice. The iterator will yield each element of the slice in order.
Example:
iter := itertools.ToIter([]int{1, 2, 3, 4})
for iter.Next() {
fmt.Println(iter.Current())
}
func Zip ¶
Zip combines two iterators element-wise into a single iterator of pairs. Iteration stops when either iterator is exhausted.
The resulting iterator yields struct values with First and Second fields.
Example:
iter1 := itertools.ToIter([]int{1, 2, 3})
iter2 := itertools.ToIter([]string{"a", "b", "c"})
zipped := itertools.Zip(iter1, iter2).Collect()
// zipped is [{First: 1, Second: "a"}, {First: 2, Second: "b"}, {First: 3, Second: "c"}]
func Zip2 ¶
func Zip2[A, B any](it1 *Iterator[A], it2 *Iterator[B], fill struct { First A Second B }) *Iterator[struct { First A Second B }]
Zip2 combines two iterators element-wise into a single iterator of pairs. Unlike Zip, if one iterator is longer than the other, the shorter one is extended using the fill values.
Example:
iter1 := itertools.ToIter([]int{1, 2, 3})
iter2 := itertools.ToIter([]string{"a"})
fill := struct{ First int; Second string }{0, ""}
zipped := itertools.Zip2(iter1, iter2, fill).Collect()
// zipped is [{1, "a"}, {2, ""}, {3, ""}]
func (*Iterator[V]) All ¶
All returns true if all elements in the iterator satisfy the predicate. Returns true for an empty iterator.
Example:
iter := itertools.ToIter([]int{2, 4, 6, 8})
allEven := iter.All(func(x int) bool { return x%2 == 0 }) // Returns true
func (*Iterator[V]) Any ¶
Any returns true if any element in the iterator satisfies the predicate. Returns false for an empty iterator.
Example:
iter := itertools.ToIter([]int{1, 3, 5, 6, 7})
hasEven := iter.Any(func(x int) bool { return x%2 == 0 }) // Returns true
func (*Iterator[V]) AssertEq ¶
AssertEq checks if the iterator elements are equal to the expected slice using the provided equality predicate. Returns true if all elements match, false otherwise.
Example:
iter := itertools.ToIter([]int{1, 2, 3})
equal := iter.AssertEq([]int{1, 2, 3}, func(a, b int) bool { return a == b })
// equal is true
func (*Iterator[V]) Chain ¶
Chain concatenates this iterator with another, yielding all elements from the first iterator followed by all elements from the second.
Chain properly handles early termination - if iteration stops early, the second iterator may not be consumed at all.
Example:
iter1 := itertools.ToIter([]int{1, 2, 3})
iter2 := itertools.ToIter([]int{4, 5, 6})
chained := iter1.Chain(iter2).Collect()
// chained is []int{1, 2, 3, 4, 5, 6}
func (*Iterator[V]) Collect ¶
func (it *Iterator[V]) Collect() []V
Collect consumes the iterator and returns all elements as a slice. After calling Collect, the iterator is exhausted.
Note: This loads all elements into memory. For large sequences, consider using streaming operations like Each or Filter.
Example:
iter := itertools.ToIter([]int{1, 2, 3, 4})
evens := iter.Filter(func(x int) bool { return x%2 == 0 }).Collect()
// evens is []int{2, 4}
func (*Iterator[V]) Compact ¶
Compact removes zero-value elements from the iterator. Zero values are detected using reflection.
Example:
iter := itertools.ToIter([]int{1, 0, 2, 0, 3})
compacted := iter.Compact().Collect()
// compacted is []int{1, 2, 3}
func (*Iterator[V]) CompactWith ¶
CompactWith removes elements that are equal to the specified zero value.
Example:
iter := itertools.ToIter([]int{1, -1, 2, -1, 3})
compacted := iter.CompactWith(-1).Collect()
// compacted is []int{1, 2, 3}
func (*Iterator[V]) Count ¶
Count returns the total number of elements in the iterator. The iterator is consumed after calling Count.
Example:
iter := itertools.ToIter([]int{1, 2, 3, 4, 5})
count := iter.Filter(func(x int) bool { return x%2 == 0 }).Count()
// count is 2
func (*Iterator[V]) Current ¶
func (it *Iterator[V]) Current() V
Current returns the current element of the iterator. It panics if called before Next() or after the iterator is exhausted.
Always call Next() before calling Current() to ensure a valid element exists.
Example:
iter := itertools.ToIter([]int{1, 2, 3})
if iter.Next() {
fmt.Println(iter.Current()) // Prints: 1
}
func (*Iterator[V]) Cycle ¶
Cycle returns an infinite iterator that repeatedly cycles through the elements.
Note: This collects all elements into memory. Be careful when using with infinite iterators or very large sequences.
Example:
iter := itertools.ToIter([]int{1, 2, 3})
cycled := iter.Cycle().Take(7).Collect()
// cycled is []int{1, 2, 3, 1, 2, 3, 1}
func (*Iterator[V]) Difference ¶
Difference returns an iterator that yields elements present in this iterator but not in the other iterator. The keyFunc extracts a comparable key for matching elements.
Note: This method consumes the other iterator to build a set of keys.
Example:
iter1 := itertools.ToIter([]int{1, 2, 3, 4})
iter2 := itertools.ToIter([]int{3, 4, 5, 6})
diff := iter1.Difference(iter2, func(x int) any { return x }).Collect()
// diff is []int{1, 2}
func (*Iterator[V]) Drop ¶
Drop returns a new iterator that skips the first n elements and yields the rest. If the iterator has n or fewer elements, the resulting iterator is empty.
Example:
iter := itertools.ToIter([]int{1, 2, 3, 4, 5})
rest := iter.Drop(2).Collect()
// rest is []int{3, 4, 5}
func (*Iterator[V]) DropWhile ¶
DropWhile returns a new iterator that skips elements while the predicate is true, then yields all remaining elements.
Example:
iter := itertools.ToIter([]int{1, 2, 3, 4, 5})
result := iter.DropWhile(func(x int) bool { return x < 3 }).Collect()
// result is []int{3, 4, 5}
func (*Iterator[V]) Each ¶
func (it *Iterator[V]) Each(f func(V))
Each applies a function to each element of the iterator. This is useful for performing side effects like printing or logging.
The iterator is consumed after calling Each.
Example:
iter := itertools.ToIter([]int{1, 2, 3})
iter.Each(func(x int) {
fmt.Println(x)
})
func (*Iterator[V]) Filter ¶
Filter returns a new iterator that only yields elements satisfying the predicate. Elements for which predicate returns false are skipped.
Filter is lazy - predicates are evaluated only as elements are consumed.
Example:
iter := itertools.ToIter([]int{1, 2, 3, 4, 5, 6})
evens := iter.Filter(func(x int) bool { return x%2 == 0 }).Collect()
// evens is []int{2, 4, 6}
func (*Iterator[V]) Find ¶
Find returns the first element that satisfies the predicate along with true, or the zero value and false if no element satisfies the predicate.
Example:
iter := itertools.ToIter([]int{1, 3, 5, 6, 7})
first, found := iter.Find(func(x int) bool { return x%2 == 0 })
// first is 6, found is true
func (*Iterator[V]) First ¶
func (it *Iterator[V]) First() V
First returns the first element of the iterator. It panics if the iterator is empty.
For a safe alternative that doesn't panic, use FirstOr.
Example:
iter := itertools.ToIter([]int{1, 2, 3})
first := iter.First() // Returns 1
func (*Iterator[V]) FirstOr ¶ added in v1.1.0
func (it *Iterator[V]) FirstOr(defaultValue V) V
FirstOr returns the first element of the iterator, or defaultValue if the iterator is empty. This is a safe alternative to First that doesn't panic.
Example:
iter := itertools.ToIter([]int{})
first := iter.FirstOr(999) // Returns 999
iter2 := itertools.ToIter([]int{1, 2, 3})
first2 := iter2.FirstOr(999) // Returns 1
func (*Iterator[V]) GroupBy ¶
GroupBy groups elements by a key function into a map where keys are strings and values are slices of elements with that key.
Example:
type Person struct { Name string; Age int }
iter := itertools.ToIter([]Person{
{"Alice", 25}, {"Bob", 30}, {"Charlie", 25},
})
byAge := iter.GroupBy(func(p Person) string {
return fmt.Sprintf("%d", p.Age)
})
// byAge["25"] is []Person{{"Alice", 25}, {"Charlie", 25}}
// byAge["30"] is []Person{{"Bob", 30}}
func (*Iterator[V]) Index ¶
Index returns the 0-based index of the first element that satisfies the predicate. Returns -1 if no element satisfies the predicate.
Example:
iter := itertools.ToIter([]int{10, 20, 30, 40, 50})
idx := iter.Index(func(x int) bool { return x == 30 })
// idx is 2
func (*Iterator[V]) Intersection ¶
Intersection returns an iterator that yields elements present in both iterators. The keyFunc extracts a comparable key for matching elements.
Note: This method consumes the other iterator to build a set of keys.
Example:
iter1 := itertools.ToIter([]int{1, 2, 3, 4})
iter2 := itertools.ToIter([]int{3, 4, 5, 6})
intersection := iter1.Intersection(iter2, func(x int) any { return x }).Collect()
// intersection is []int{3, 4}
func (*Iterator[V]) IsSorted ¶
IsSorted returns true if the elements are sorted according to the less function. Returns true for empty iterators and single-element iterators.
Example:
iter := itertools.ToIter([]int{1, 2, 3, 4, 5})
sorted := iter.IsSorted(func(a, b int) bool { return a < b })
// sorted is true
func (*Iterator[V]) Last ¶
func (it *Iterator[V]) Last() V
Last returns the last element of the iterator. It panics if the iterator is empty.
For a safe alternative that doesn't panic, use LastOr.
Note: This method collects all elements into memory.
Example:
iter := itertools.ToIter([]int{1, 2, 3})
last := iter.Last() // Returns 3
func (*Iterator[V]) LastIndex ¶
LastIndex returns the 0-based index of the last element that satisfies the predicate. Returns -1 if no element satisfies the predicate.
Example:
iter := itertools.ToIter([]int{10, 20, 30, 20, 50})
idx := iter.LastIndex(func(x int) bool { return x == 20 })
// idx is 3
func (*Iterator[V]) LastOr ¶ added in v1.1.0
func (it *Iterator[V]) LastOr(defaultValue V) V
LastOr returns the last element of the iterator, or defaultValue if the iterator is empty. This is a safe alternative to Last that doesn't panic.
Note: This method must consume the entire iterator.
Example:
iter := itertools.ToIter([]int{})
last := iter.LastOr(999) // Returns 999
iter2 := itertools.ToIter([]int{1, 2, 3})
last2 := iter2.LastOr(999) // Returns 3
func (*Iterator[V]) Map ¶
Map transforms each element using the provided function and returns a new iterator.
Map is lazy - the transformation is applied only as elements are consumed.
Example:
iter := itertools.ToIter([]int{1, 2, 3, 4})
squared := iter.Map(func(x int) int { return x * x }).Collect()
// squared is []int{1, 4, 9, 16}
func (*Iterator[V]) Max ¶
Max returns the maximum element according to the less function, along with true. Returns the zero value and false if the iterator is empty.
Example:
iter := itertools.ToIter([]int{3, 1, 4, 1, 5})
max, found := iter.Max(func(a, b int) bool { return a < b })
// max is 5, found is true
func (*Iterator[V]) Min ¶
Min returns the minimum element according to the less function, along with true. Returns the zero value and false if the iterator is empty.
Example:
iter := itertools.ToIter([]int{3, 1, 4, 1, 5})
min, found := iter.Min(func(a, b int) bool { return a < b })
// min is 1, found is true
func (*Iterator[V]) Next ¶
Next advances the iterator to the next element and returns true if successful. It returns false when the iterator is exhausted.
Next must be called before accessing the current element via Current(). After Next returns false, subsequent calls will continue to return false.
Example:
iter := itertools.ToIter([]int{1, 2, 3})
for iter.Next() {
fmt.Println(iter.Current())
}
func (*Iterator[V]) Nth ¶
Nth returns the nth element (0-indexed) of the iterator. It panics if the iterator has fewer than n+1 elements.
For a safe alternative that doesn't panic, use NthOr.
Example:
iter := itertools.ToIter([]int{10, 20, 30, 40})
third := iter.Nth(2) // Returns 30
func (*Iterator[V]) NthOr ¶ added in v1.1.0
NthOr returns the nth element (0-indexed) of the iterator, or defaultValue if there aren't enough elements. This is a safe alternative to Nth that doesn't panic.
Example:
iter := itertools.ToIter([]int{10, 20, 30})
third := iter.NthOr(2, 999) // Returns 30
fifth := iter.NthOr(4, 999) // Returns 999 (not enough elements)
func (*Iterator[V]) Partition ¶
func (it *Iterator[V]) Partition(predicate func(V) bool) (matched *Iterator[V], unmatched *Iterator[V])
Partition splits the iterator into two iterators: one with elements that satisfy the predicate, and one with elements that don't.
Note: This method collects all elements into memory.
Example:
iter := itertools.ToIter([]int{1, 2, 3, 4, 5, 6})
evens, odds := iter.Partition(func(x int) bool { return x%2 == 0 })
// evens.Collect() is []int{2, 4, 6}
// odds.Collect() is []int{1, 3, 5}
func (*Iterator[V]) Replace ¶
Replace returns an iterator that replaces elements satisfying the predicate with the replacement value.
Example:
iter := itertools.ToIter([]int{1, 2, 3, 4, 5})
replaced := iter.Replace(func(x int) bool { return x%2 == 0 }, 0).Collect()
// replaced is []int{1, 0, 3, 0, 5}
func (*Iterator[V]) ReplaceAll ¶
ReplaceAll returns an iterator that replaces all elements with the replacement value.
Example:
iter := itertools.ToIter([]int{1, 2, 3, 4, 5})
replaced := iter.ReplaceAll(0).Collect()
// replaced is []int{0, 0, 0, 0, 0}
func (*Iterator[V]) Reverse ¶
Reverse returns a new iterator that yields elements in reverse order.
Note: This method collects all elements into memory to reverse them, so it's not suitable for infinite iterators.
Example:
iter := itertools.ToIter([]int{1, 2, 3, 4})
reversed := iter.Reverse().Collect()
// reversed is []int{4, 3, 2, 1}
func (*Iterator[V]) Shuffle ¶
Shuffle returns an iterator that yields elements in random order.
Note: This collects all elements into memory to shuffle them.
Example:
iter := itertools.ToIter([]int{1, 2, 3, 4, 5})
shuffled := iter.Shuffle().Collect()
// shuffled is []int in random order, e.g., []int{3, 1, 5, 2, 4}
func (*Iterator[V]) Sort ¶
Sort returns a new iterator with elements sorted according to the less function.
Note: This method collects all elements into memory to sort them.
Example:
iter := itertools.ToIter([]int{3, 1, 4, 1, 5})
sorted := iter.Sort(func(a, b int) bool { return a < b }).Collect()
// sorted is []int{1, 1, 3, 4, 5}
func (*Iterator[V]) StepBy ¶
StepBy returns an iterator that yields every nth element (0-indexed).
Example:
iter := itertools.ToIter([]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9})
everyThird := iter.StepBy(3).Collect()
// everyThird is []int{0, 3, 6, 9}
func (*Iterator[V]) String ¶
String returns a string representation of the iterator by collecting all elements.
Note: This consumes the iterator and loads all elements into memory.
Example:
iter := itertools.ToIter([]int{1, 2, 3})
str := iter.String()
// str is "<Iterator: [1 2 3]>"
func (*Iterator[V]) Take ¶
Take returns a new iterator that yields at most the first n elements. If the iterator has fewer than n elements, all elements are yielded.
Take is lazy and supports early termination.
Example:
iter := itertools.ToIter([]int{1, 2, 3, 4, 5})
first3 := iter.Take(3).Collect()
// first3 is []int{1, 2, 3}
func (*Iterator[V]) TakeWhile ¶
TakeWhile returns a new iterator that yields elements while the predicate is true. Once the predicate returns false for an element, iteration stops.
Example:
iter := itertools.ToIter([]int{1, 2, 3, 4, 5, 1, 2})
result := iter.TakeWhile(func(x int) bool { return x < 4 }).Collect()
// result is []int{1, 2, 3}
func (*Iterator[V]) ToLower ¶
ToLower converts string elements to lowercase. Non-string elements are unchanged.
Example:
iter := itertools.ToIter([]string{"HELLO", "WORLD"})
lower := iter.ToLower().Collect()
// lower is []string{"hello", "world"}
func (*Iterator[V]) ToUpper ¶
ToUpper converts string elements to uppercase. Non-string elements are unchanged.
Example:
iter := itertools.ToIter([]string{"hello", "world"})
upper := iter.ToUpper().Collect()
// upper is []string{"HELLO", "WORLD"}
func (*Iterator[V]) TrimSpace ¶
TrimSpace trims whitespace from string elements. Non-string elements are unchanged.
Example:
iter := itertools.ToIter([]string{" hello ", " world "})
trimmed := iter.TrimSpace().Collect()
// trimmed is []string{"hello", "world"}
func (*Iterator[V]) Union ¶
Union returns an iterator that yields elements from both iterators without duplicates. The keyFunc extracts a comparable key to detect duplicates.
Note: This method consumes both iterators and tracks seen keys in memory.
Example:
iter1 := itertools.ToIter([]int{1, 2, 3})
iter2 := itertools.ToIter([]int{3, 4, 5})
union := iter1.Union(iter2, func(x int) any { return x }).Collect()
// union is []int{1, 2, 3, 4, 5}
func (*Iterator[V]) Unique ¶
Unique returns a new iterator that yields only unique elements based on the key function. The keyFunc extracts a comparable key from each element.
Each iteration creates a fresh set for tracking seen elements, making it safe to iterate multiple times.
Example:
iter := itertools.ToIter([]int{1, 2, 2, 3, 3, 3, 4})
unique := iter.Unique(func(x int) any { return x }).Collect()
// unique is []int{1, 2, 3, 4}
type Productable ¶
type Productable interface {
constraints.Integer | constraints.Float | constraints.Complex
}
Productable is a constraint for types that support multiplication.