Skip to main content

seq2

import "github.com/go-softwarelab/common/pkg/seq2"

Package seq2 provides a comprehensive set of utilities for working with key-value sequences in Go applications.

The goal of this package is to offer a rich set of functions for creating, transforming, and consuming iter.Seq2, enabling developers to work with collections of key-value pairs in a functional programming style. The package includes utilities for filtering, mapping, reducing, and sorting sequences, as well as combining and partitioning them.

The package is designed to reduce boilerplate code and improve readability by providing a consistent API for common sequence operations. It leverages Go's type safety and generics to ensure that operations on sequences are both flexible and safe. The Sequence struct is worth mentioning explicitly, allowing method chaining and fluent composition of sequence operations.

Append​

func Append[K any, V any](seq iter.Seq2[K, V], key K, value V) iter.Seq2[K, V]

Append appends element to the end of a sequence.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.FromMap(map[string]int{"a": 1, "b": 2})
input = seq2.SortByKeys(input)

// Append a new key-value pair to the sequence
appended := seq2.Append(input, "c", 3)

result := seq2.CollectToMap(appended)
fmt.Println(result)
}

Output

map[a:1 b:2 c:3]

Collect​

func Collect[K comparable, V any](seq iter.Seq2[K, V]) []types.Pair[K, V]

Collect collects the elements of the given sequence into a slice of types.Pair of K and V.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.FromMap(map[string]int{"a": 1, "b": 2, "c": 3})
input = seq2.SortByKeys(input)

result := seq2.Collect(input)

fmt.Println(result)

}

Output

[{a 1} {b 2} {c 3}]

CollectToMap​

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

CollectToMap collects the elements of the given sequence into a map.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.FromMap(map[string]int{"a": 1, "b": 2, "c": 3})
input = seq2.SortByKeys(input)

result := seq2.CollectToMap(input)

fmt.Println(result)
}

Output

map[a:1 b:2 c:3]

Concat​

func Concat[K any, V any](sequences ...iter.Seq2[K, V]) iter.Seq2[K, V]

Concat concatenates multiple sequences into a single sequence. It also safely handles nil iterators treating them as an empty iterator.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
first := seq2.FromMap(map[string]int{"a": 1, "b": 2})
first = seq2.SortByKeys(first)
second := seq2.FromMap(map[string]int{"c": 3, "d": 4})
second = seq2.SortByKeys(second)

// Concatenate two sequences
combined := seq2.Concat(first, second, nil)

result := seq2.CollectToMap(combined)
fmt.Println(result)
}

Output

map[a:1 b:2 c:3 d:4]

Contains​

func Contains[K comparable, V any](seq iter.Seq2[K, V], key K) bool

Contains returns true if the key is in the sequence.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.FromMap(map[string]int{"a": 1, "b": 2, "c": 3, "d": 4})
input = seq2.SortByKeys(input)

contains := seq2.Contains(input, "b")

fmt.Println(contains)
}

Output

true

ContainsAll​

func ContainsAll[K comparable, V any](seq iter.Seq2[K, V], keys ...K) bool

ContainsAll returns true if all keys are in the sequence.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.FromMap(map[string]int{"a": 1, "b": 2, "c": 3, "d": 4})
input = seq2.SortByKeys(input)

containsAll := seq2.ContainsAll(input, "a", "c", "d")

fmt.Println(containsAll)
}

Output

true

ContainsAllValues​

func ContainsAllValues[K any, V comparable](seq iter.Seq2[K, V], values ...V) bool

ContainsAllValues returns true if all values are in the sequence.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.FromMap(map[string]int{"a": 1, "b": 2, "c": 3, "d": 4})
input = seq2.SortByKeys(input)

containsAllValues := seq2.ContainsAllValues(input, 1, 3)

fmt.Println(containsAllValues)
}

Output

true

ContainsPair​

func ContainsPair[K comparable, V comparable](seq iter.Seq2[K, V], key K, value V) bool

ContainsPair returns true if the key-value pair is in the sequence.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.FromMap(map[string]int{"a": 1, "b": 2, "c": 3, "d": 4})
input = seq2.SortByKeys(input)

containsPair := seq2.ContainsPair(input, "b", 2)

fmt.Println(containsPair)
}

Output

true

ContainsValue​

func ContainsValue[K any, V comparable](seq iter.Seq2[K, V], value V) bool

ContainsValue returns true if the value is in the sequence.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.FromMap(map[string]int{"a": 1, "b": 2, "c": 3, "d": 4})
input = seq2.SortByKeys(input)

containsValue := seq2.ContainsValue(input, 3)

fmt.Println(containsValue)
}

Output

true

Count​

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

Count returns the number of elements in the sequence.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.FromMap(map[string]int{"a": 1, "b": 2, "c": 3})
input = seq2.SortByKeys(input)

// Count returns the number of elements in the sequence
count := seq2.Count(input)

fmt.Println(count)
}

Output

3

Cycle​

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

Cycle repeats the sequence indefinitely.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.FromMap(map[string]int{"a": 1, "b": 2})
input = seq2.SortByKeys(input)

// Create an infinite cycle of the sequence
cycled := seq2.Cycle(input)

// Take only the first 5 elements from the infinite cycle
limited := seq2.Take(cycled, 5)

seq2.ForEach(limited, func(k string, v int) {
fmt.Println(k, v)
})

}

Output

a 1
b 2
a 1
b 2
a 1

CycleTimes​

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

CycleTimes repeats the sequence count times.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.FromMap(map[string]int{"a": 1, "b": 2})
input = seq2.SortByKeys(input)

// Repeat the sequence 2 times
cycled := seq2.CycleTimes(input, 2)

seq2.ForEach(cycled, func(k string, v int) {
fmt.Println(k, v)
})

}

Output

a 1
b 2
a 1
b 2

Distinct​

func Distinct[K comparable, V comparable](seq iter.Seq2[K, V]) iter.Seq2[K, V]

Distinct returns a new sequence that contains only the unique elements of the given sequence. SQL-like alias for Uniq.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
// Create a sequence with duplicate key-value pairs
input := seq2.Concat(
seq2.FromMap(map[string]int{"a": 1, "b": 2}),
seq2.FromMap(map[string]int{"a": 1, "c": 3}),
)

// Distinct is an alias for Uniq
unique := seq2.Distinct(input)

result := seq2.CollectToMap(unique)
fmt.Println(result)
}

Output

map[a:1 b:2 c:3]

DistinctKeys​

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

DistinctKeys returns a new sequence that contains only the unique keys of the given sequence.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
// Create a sequence with duplicate keys
input := seq2.Concat(
seq2.FromMap(map[string]int{"a": 1, "b": 2}),
seq2.FromMap(map[string]int{"a": 3, "c": 4}),
)

// DistinctKeys is an alias for UniqKeys
unique := seq2.DistinctKeys(input)

result := seq2.CollectToMap(unique)
fmt.Println(result)
}

Output

map[a:1 b:2 c:4]

Each​

func Each[K any, V any](seq iter.Seq2[K, V], consumer Consumer[K, V]) iter.Seq2[K, V]

Each returns a sequence that applies the given consumer to each element of the input sequence and pass it further. Each is an alias for Tap. Comparing to ForEach, this is a lazy function and doesn't consume the input sequence.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.FromMap(map[string]int{"a": 1, "b": 2, "c": 3})
input = seq2.SortByKeys(input)

tapped := seq2.Each(input, func(k string, v int) {
fmt.Printf("Each: %s -> %d\n", k, v)
})

seq2.Flush(tapped)

}

Output

Each: a -> 1
Each: b -> 2
Each: c -> 3

Empty​

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

Empty returns an empty sequence.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
// Create an empty sequence
empty := seq2.Empty[any, any]()

seq2.ForEach(empty, func(any, any) {
fmt.Println("Should not be called")
})
}

Output

Every​

func Every[K, V any](seq iter.Seq2[K, V], predicate Predicate[K, V]) bool

Every returns true if all elements satisfy the predicate.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.FromMap(map[string]int{"a": 2, "b": 4, "c": 6, "d": 8})
input = seq2.SortByKeys(input)

every := seq2.Every(input, func(k string, v int) bool {
return v%2 == 0
})

fmt.Println(every)
}

Output

true

Exists​

func Exists[K, V any](seq iter.Seq2[K, V], predicate Predicate[K, V]) bool

Exists returns true if there is at least one element that satisfies the predicate.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.FromMap(map[string]int{"a": 1, "b": 2, "c": 3, "d": 4})
input = seq2.SortByKeys(input)

exists := seq2.Exists(input, func(k string, v int) bool {
return k > "c" && v > 3
})

fmt.Println(exists)
}

Output

true

Filter​

func Filter[K any, V any](seq iter.Seq2[K, V], predicate Predicate[K, V]) iter.Seq2[K, V]

Filter returns a new sequence that contains only the elements that satisfy the predicate.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.FromMap(map[string]int{"a": 1, "b": 2, "c": 3, "d": 4})
input = seq2.SortByKeys(input)

// Filter elements where the value is even
filtered := seq2.Filter(input, func(k string, v int) bool {
return v%2 == 0
})

result := seq2.CollectToMap(filtered)
fmt.Println(result)
}

Output

map[b:2 d:4]

FilterByKey​

func FilterByKey[K any, V any](seq iter.Seq2[K, V], predicate KeyPredicate[K]) iter.Seq2[K, V]

FilterByKey returns a new sequence that contains only the elements that satisfy the predicate.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.FromMap(map[string]int{"a": 1, "b": 2, "c": 3, "d": 4})
input = seq2.SortByKeys(input)

// Filter elements by key
filtered := seq2.FilterByKey(input, func(k string) bool {
return k > "b"
})

result := seq2.CollectToMap(filtered)
fmt.Println(result)
}

Output

map[c:3 d:4]

FilterByValue​

func FilterByValue[K any, V any](seq iter.Seq2[K, V], predicate ValuePredicate[V]) iter.Seq2[K, V]

FilterByValue returns a new sequence that contains only the elements that satisfy the predicate.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.FromMap(map[string]int{"a": 1, "b": 2, "c": 3, "d": 4})
input = seq2.SortByKeys(input)

// Filter elements by value
filtered := seq2.FilterByValue(input, func(v int) bool {
return v <= 2
})

result := seq2.CollectToMap(filtered)
fmt.Println(result)
}

Output

map[a:1 b:2]

FindAll​

func FindAll[K, V any](seq iter.Seq2[K, V], predicate Predicate[K, V]) iter.Seq2[K, V]

FindAll returns all elements that satisfy the predicate.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.FromMap(map[string]int{"a": 1, "b": 2, "c": 3, "d": 4})
input = seq2.SortByKeys(input)

found := seq2.FindAll(input, func(k string, v int) bool {
return v > 2
})

result := seq2.CollectToMap(found)
fmt.Println(result)
}

Output

map[c:3 d:4]

Flush​

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

Flush consumes all elements of the input sequence.

Example
package main

import (
"fmt"
"iter"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
// Create a sequence that has side effects when consumed
sideEffects := iter.Seq2[string, int](func(yield func(string, int) bool) {
fmt.Println("First element consumed")
if !yield("a", 1) {
return
}
fmt.Println("Second element consumed")
if !yield("b", 2) {
return
}
fmt.Println("Third element consumed")
if !yield("c", 3) {
return
}
})

// Flush consumes all elements without doing anything with them
seq2.Flush(sideEffects)

}

Output

First element consumed
Second element consumed
Third element consumed

ForEach​

func ForEach[K any, V any](seq iter.Seq2[K, V], consumer Consumer[K, V])

ForEach applies consumer to each element of the input sequence. Comparing to Each, this is not a lazy function and consumes the input sequence.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.OfIndexed("a", "b", "c")

// ForEach consumes the sequence and applies the function
seq2.ForEach(input, func(k int, v string) {
fmt.Printf("%d: %s\n", k, v)
})

}

Output

0: a
1: b
2: c

FromMap​

func FromMap[Map ~map[K]V, K comparable, V any](m Map) iter.Seq2[K, V]

FromMap creates a new iter.Seq2 from the given map.

FromSlice​

func FromSlice[Slice ~[]E, E any](slice Slice) iter.Seq2[int, E]

FromSlice creates a new sequence from the given slice with index as keys.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
// Create a sequence from a slice
slice := []string{"a", "b", "c"}
sequence := seq2.FromSlice(slice)

result := seq2.CollectToMap(sequence)
fmt.Println(result)
}

Output

map[0:a 1:b 2:c]

Get​

func Get[K comparable, V any](seq iter.Seq2[K, V], key K) optional.Value[V]

Get returns the element at the specified key.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.FromMap(map[string]int{"a": 1, "b": 2, "c": 3, "d": 4})
input = seq2.SortByKeys(input)

value := seq2.Get(input, "c")

fmt.Println(value.MustGet())
}

Output

3

IsEmpty​

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

IsEmpty returns true if the sequence is empty.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
emptySeq := seq2.Empty[any, any]()

nonEmptySeq := seq2.OfIndexed("a")

fmt.Printf("Empty sequence: %v\n", seq2.IsEmpty(emptySeq))
fmt.Printf("Non-empty sequence: %v\n", seq2.IsEmpty(nonEmptySeq))
}

Output

Empty sequence: true
Non-empty sequence: false

IsNotEmpty​

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

IsNotEmpty returns true if the sequence is not empty.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
emptySeq := seq2.Empty[any, any]()

nonEmptySeq := seq2.OfIndexed("a")

fmt.Printf("Empty sequence: %v\n", seq2.IsNotEmpty(emptySeq))
fmt.Printf("Non-empty sequence: %v\n", seq2.IsNotEmpty(nonEmptySeq))
}

Output

Empty sequence: false
Non-empty sequence: true

Keys​

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

Keys returns a sequence of keys from a sequence of key-value pairs.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq"
"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.OfIndexed("a", "b", "c")

keys := seq2.Keys(input)

seq.ForEach(keys, func(k int) {
fmt.Print(k, " ")
})
}

Output

0 1 2

Limit​

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

Limit returns a new sequence that contains only the first n elements of the given sequence. SQL-like alias for Take.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.FromMap(map[string]int{"a": 1, "b": 2, "c": 3, "d": 4})
input = seq2.SortByKeys(input)

// Limit is an alias for Take
taken := seq2.Limit(input, 3)

result := seq2.CollectToMap(taken)
fmt.Println(result)
}

Output

map[a:1 b:2 c:3]

Map​

func Map[K, V, RK, RV any](seq iter.Seq2[K, V], mapper DoubleMapper[K, V, RK, RV]) iter.Seq2[RK, RV]

Map applies a mapper function to each element of the sequence.

Example
package main

import (
"fmt"
"strings"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.FromMap(map[string]int{"a": 1, "b": 2, "c": 3})
input = seq2.SortByKeys(input)

// Map both key and value to produce a new value (keeps original keys)
mapped := seq2.Map(input, func(k string, v int) (string, int) {
return strings.ToUpper(k), v * 10
})

result := seq2.CollectToMap(mapped)
fmt.Println(result)
}

Output

map[A:10 B:20 C:30]

MapKeys​

func MapKeys[K, V, RK any](seq iter.Seq2[K, V], mapper KeyMapper[K, RK]) iter.Seq2[RK, V]

MapKeys applies a mapper function to each key of the sequence.

Example
package main

import (
"fmt"
"strings"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.FromMap(map[string]int{"a": 1, "b": 2, "c": 3})
input = seq2.SortByKeys(input)

// Map keys to uppercase (keeps original values)
mapped := seq2.MapKeys(input, func(k string) string {
return strings.ToUpper(k)
})

result := seq2.CollectToMap(mapped)
fmt.Println(result)
}

Output

map[A:1 B:2 C:3]

MapTo​

func MapTo[K, V, RV any](seq iter.Seq2[K, V], mapper Mapper[K, V, RV]) iter.Seq[RV]

MapTo applies a mapper function to each element of the sequence and returns a sequence of mapper results.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq"
"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.FromMap(map[string]int{"a": 1, "b": 2, "c": 3})
input = seq2.SortByKeys(input)

// Map each key-value pair to a string
mapped := seq2.MapTo(input, func(k string, v int) string {
return fmt.Sprintf("%s=%d", k, v)
})

seq.ForEach(mapped, func(v string) {
fmt.Println(v)
})
}

Output

a=1
b=2
c=3

MapValues​

func MapValues[K, V, RV any](seq iter.Seq2[K, V], mapper ValueMapper[V, RV]) iter.Seq2[K, RV]

MapValues applies a mapper function to each value of the sequence.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.FromMap(map[string]int{"a": 1, "b": 2, "c": 3})
input = seq2.SortByKeys(input)

// Map values to their squares (keeps original keys)
mapped := seq2.MapValues(input, func(v int) int {
return v * v
})

result := seq2.CollectToMap(mapped)
fmt.Println(result)
}

Output

map[a:1 b:4 c:9]

None​

func None[K, V any](seq iter.Seq2[K, V], predicate Predicate[K, V]) bool

None returns true if no element satisfies the predicate.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.FromMap(map[string]int{"a": 1, "b": 2, "c": 3, "d": 4})
input = seq2.SortByKeys(input)

none := seq2.None(input, func(k string, v int) bool {
return v > 10
})

fmt.Println(none)
}

Output

true

NotContains​

func NotContains[K comparable, V any](seq iter.Seq2[K, V], key K) bool

NotContains returns true if the key is not in the sequence.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.FromMap(map[string]int{"a": 1, "b": 2, "c": 3, "d": 4})
input = seq2.SortByKeys(input)

notContains := seq2.NotContains(input, "x")

fmt.Println(notContains)
}

Output

true

NotContainsPair​

func NotContainsPair[K comparable, V comparable](seq iter.Seq2[K, V], key K, value V) bool

NotContainsPair returns true if the key-value pair is not in the sequence.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.FromMap(map[string]int{"a": 1, "b": 2, "c": 3, "d": 4})
input = seq2.SortByKeys(input)

notContainsPair := seq2.NotContainsPair(input, "b", 3)

fmt.Println(notContainsPair)
}

Output

true

NotContainsValue​

func NotContainsValue[K any, V comparable](seq iter.Seq2[K, V], value V) bool

NotContainsValue returns true if the value is not in the sequence.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.FromMap(map[string]int{"a": 1, "b": 2, "c": 3, "d": 4})
input = seq2.SortByKeys(input)

notContainsValue := seq2.NotContainsValue(input, 5)

fmt.Println(notContainsValue)
}

Output

true

OfIndexed​

func OfIndexed[E any](elems ...E) iter.Seq2[int, E]

OfIndexed creates a new indexed sequence from the given elements.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
// Create a sequence from individual elements
indexed := seq2.OfIndexed(1, 2, 3)

result := seq2.CollectToMap(indexed)
fmt.Println(result)
}

Output

map[0:1 1:2 2:3]

Offset​

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

Offset returns a new sequence that skips the first n elements of the given sequence. SQL-like alias for Skip.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.OfIndexed(10, 20, 30, 40, 20)

// Skip the first 2 elements
skipped := seq2.Offset(input, 2)

result := seq2.CollectToMap(skipped)
fmt.Println(result)
}

Output

map[2:30 3:40 4:20]

Prepend​

func Prepend[K any, V any](seq iter.Seq2[K, V], key K, value V) iter.Seq2[K, V]

Prepend prepends element to the beginning of a sequence.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.FromMap(map[string]int{"b": 2, "c": 3})
input = seq2.SortByKeys(input)

// Prepend a new key-value pair to the sequence
prepended := seq2.Prepend(input, "a", 1)

result := seq2.CollectToMap(prepended)
fmt.Println(result)
}

Output

map[a:1 b:2 c:3]

Reduce​

func Reduce[K any, V any, R any](seq2 iter.Seq2[K, V], accumulator func(agg R, key K, value V) R, initial R) R

Reduce applies a function against an accumulator and each element in the sequence (from left to right) to reduce it to a single value.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
type Reduced struct {
Key string
Value int
}

input := seq2.FromMap(map[string]int{"a": 1, "b": 2, "c": 3})
input = seq2.SortByKeys(input)

// Reduce to calculate the sum of all values
reduced := seq2.Reduce(input, func(agg Reduced, key string, value int) Reduced {
return Reduced{
Key: agg.Key + key,
Value: agg.Value + value,
}
}, Reduced{})

fmt.Println(reduced)
}

Output

{abc 6}

ReduceRight​

func ReduceRight[K any, V any, R any](seq2 iter.Seq2[K, V], accumulator func(agg R, key K, value V) R, initial R) R

ReduceRight applies a function against an accumulator and each element in the sequence (from right to left) to reduce it to a single value.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
type Reduced struct {
Key string
Value int
}

input := seq2.FromMap(map[string]int{"a": 1, "b": 2, "c": 3})
input = seq2.SortByKeys(input)

// Reduce to calculate the sum of all values
reduced := seq2.ReduceRight(input, func(agg Reduced, key string, value int) Reduced {
return Reduced{
Key: agg.Key + key,
Value: agg.Value + value,
}
}, Reduced{})

fmt.Println(reduced)
}

Output

{cba 6}

Repeat​

func Repeat[K any, V any, N types.Integer](key K, value V, count N) iter.Seq2[K, V]

Repeat repeats the given pair `count` times.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
// Create a sequence that repeats a key-value pair 3 times
repeated := seq2.Repeat("key", 42, 3)

seq2.ForEach(repeated, func(k string, v int) {
fmt.Println(k, ":", v)
})
}

Output

key : 42
key : 42
key : 42

Reverse​

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

Reverse reverses the given sequence.

Example
package main

import (
"fmt"
"strings"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
// Create an indexed sequence
sequence := seq2.OfIndexed("a", "b", "c")

// Reverse it
reversed := seq2.Reverse(sequence)

// CollectToMap into pairs for ordered display
var pairs []string
seq2.ForEach(reversed, func(k int, v string) {
fmt.Println(k, ":", v)
})

fmt.Println(strings.Join(pairs, ", "))
}

Output

2 : c
1 : b
0 : a

Single​

func Single[K, V any](k K, v V) iter.Seq2[K, V]

Single returns a sequence with given key value.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
// Create a sequence with a single key-value pair
single := seq2.Single("key", 42)

seq2.ForEach(single, func(k string, v int) {
fmt.Println(k, ":", v)
})
}

Output

key : 42

Skip​

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

Skip returns a new sequence that skips the first n elements of the given sequence.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.OfIndexed(10, 20, 30, 40, 20)

// Skip the first 2 elements
skipped := seq2.Skip(input, 2)

result := seq2.CollectToMap(skipped)
fmt.Println(result)
}

Output

map[2:30 3:40 4:20]

SkipUntil​

func SkipUntil[K any, V any](seq iter.Seq2[K, V], predicate Predicate[K, V]) iter.Seq2[K, V]

SkipUntil returns a new sequence that skips elements from the given sequence until the predicate is satisfied.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.OfIndexed(10, 20, 30, 40, 20)

// Skip elements until value of 30 is reached
skipped := seq2.SkipUntil(input, func(k int, v int) bool {
return v == 30
})

result := seq2.CollectToMap(skipped)
fmt.Println(result)
}

Output

map[2:30 3:40 4:20]

SkipWhile​

func SkipWhile[K any, V any](seq iter.Seq2[K, V], predicate Predicate[K, V]) iter.Seq2[K, V]

SkipWhile returns a new sequence that skips elements from the given sequence while the predicate is satisfied.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.OfIndexed(10, 20, 30, 40, 20)

// Skip elements until the value is less than 30
skipped := seq2.SkipWhile(input, func(k int, v int) bool {
return v < 30
})

result := seq2.CollectToMap(skipped)
fmt.Println(result)
}

Output

map[2:30 3:40 4:20]

SortBy​

func SortBy[K any, V any, R types.Ordered](seq iter.Seq2[K, V], mapper func(K, V) R) iter.Seq2[K, V]

SortBy sorts the elements of a sequence by result of the mapper.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.Single("a", 1)
input = seq2.Append(input, "c", 3)
input = seq2.Append(input, "b", 2)

// Sort by values
sorted := seq2.SortBy(input, func(k string, v int) int {
return v
})

seq2.ForEach(sorted, func(k string, v int) {
fmt.Println(k, ":", v)
})
}

Output

a : 1
b : 2
c : 3

SortByKeys​

func SortByKeys[K types.Ordered, V any](seq iter.Seq2[K, V]) iter.Seq2[K, V]

SortByKeys sorts the elements of a sequence by key in ascending order.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.Single("a", 1)
input = seq2.Append(input, "c", 3)
input = seq2.Append(input, "b", 2)

// SortByKeys by keys (alphabetically)
sorted := seq2.SortByKeys(input)

seq2.ForEach(sorted, func(k string, v int) {
fmt.Println(k, ":", v)
})
}

Output

a : 1
b : 2
c : 3

SortComparingKeys​

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

SortComparingKeys sorts the elements of a sequence by key in ascending order.

Example
package main

import (
"cmp"
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.Single("a", 1)
input = seq2.Append(input, "c", 3)
input = seq2.Append(input, "b", 2)

// Sort by keys in reverse order
sorted := seq2.SortComparingKeys(input, func(a, b string) int {
return -cmp.Compare(a, b)
})

seq2.ForEach(sorted, func(k string, v int) {
fmt.Println(k, ":", v)
})
}

Output

c : 3
b : 2
a : 1

SortComparingValues​

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

SortComparingValues sorts the elements of a sequence by value in ascending order.

Example
package main

import (
"cmp"
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
// Unordered map with string keys
input := seq2.Single("a", 1)
input = seq2.Append(input, "c", 3)
input = seq2.Append(input, "b", 2)

// Sort by values in descending order
sorted := seq2.SortComparingValues(input, func(a, b int) int {
return -cmp.Compare(a, b)
})

seq2.ForEach(sorted, func(k string, v int) {
fmt.Println(k, ":", v)
})
}

Output

c : 3
b : 2
a : 1

Split​

func Split[K any, V any](sequence iter.Seq2[K, V]) (iter.Seq[K], iter.Seq[V])

Split splits a sequence of pairs into two sequences.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.FromMap(map[string]int{"a": 1, "b": 2, "c": 3})
input = seq2.SortByKeys(input)

// Split is an alias for UnZip
keys, values := seq2.Split(input)

keySlice := make([]string, 0)
for k := range keys {
keySlice = append(keySlice, k)
}
fmt.Printf("Keys: %v\n", keySlice)

valueSlice := make([]int, 0)
for v := range values {
valueSlice = append(valueSlice, v)
}
fmt.Printf("Values: %v\n", valueSlice)
}

Output

Keys: [a b c]
Values: [1 2 3]

Take​

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

Take returns a new sequence that contains only the first n elements of the given sequence.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.FromMap(map[string]int{"a": 1, "b": 2, "c": 3, "d": 4})
input = seq2.SortByKeys(input)

// Take the first 2 elements
taken := seq2.Take(input, 2)

result := seq2.CollectToMap(taken)
fmt.Println(result)
}

Output

map[a:1 b:2]

TakeUntil​

func TakeUntil[K any, V any](seq iter.Seq2[K, V], predicate Predicate[K, V]) iter.Seq2[K, V]

TakeUntil returns a new sequence that takes elements from the given sequence until the predicate is satisfied.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.FromMap(map[string]int{"a": 1, "b": 2, "c": 3, "d": 4})
input = seq2.SortByKeys(input)

// Take elements until value is greater than 2
taken := seq2.TakeUntil(input, func(k string, v int) bool {
return v > 2
})

result := seq2.CollectToMap(taken)
fmt.Println(result)
}

Output

map[a:1 b:2]

TakeWhile​

func TakeWhile[K any, V any](seq iter.Seq2[K, V], predicate Predicate[K, V]) iter.Seq2[K, V]

TakeWhile returns a new sequence that takes elements from the given sequence while the predicate is satisfied.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.OfIndexed("a", "b", "c", "d")

// Take elements while value is less than 3
taken := seq2.TakeWhile(input, func(k int, v string) bool {
return v != "c"
})

result := seq2.CollectToMap(taken)
fmt.Println(result)
}

Output

map[0:a 1:b]

Tap​

func Tap[K any, V any](seq iter.Seq2[K, V], consumer Consumer[K, V]) iter.Seq2[K, V]

Tap returns a sequence that applies the given consumer to each element of the input sequence and pass it further.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.FromMap(map[string]int{"a": 1, "b": 2, "c": 3})
// Ensure to have consistent output
input = seq2.SortByKeys(input)

// Use Tap to print key-value pairs while passing them through
tapped := seq2.Tap(input, func(k string, v int) {
fmt.Printf("Processing: %s => %d\n", k, v)
})

seq2.Flush(tapped)

}

Output

Processing: a => 1
Processing: b => 2
Processing: c => 3

Tick​

func Tick(d time.Duration) iter.Seq2[int, time.Time]

Tick returns a sequence that yields the tick number and the current time every duration.

Example
package main

import (
"fmt"
"time"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
ticker := seq2.Tick(1 * time.Millisecond)

ticker = seq2.Take(ticker, 5)

seq2.ForEach(ticker, func(tick int, v time.Time) {
fmt.Printf("tick %d at %s \n", tick, v.Format("15:04:05.000"))
})

// Example Output:
// tick 1 at 00:00:00.000
// tick 2 at 00:00:00.001
// tick 3 at 00:00:00.002
// tick 4 at 00:00:00.003
// tick 5 at 00:00:00.004
}

ToMap​

func ToMap[Map ~map[K]V, K comparable, V any](seq iter.Seq2[K, V], m Map)

ToMap collects the elements of the given sequence into a map.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.FromMap(map[string]int{"a": 1, "b": 2, "c": 3})
input = seq2.SortByKeys(input)

result := make(map[string]int, 3)
seq2.ToMap(input, result)

fmt.Println(result)
}

Output

map[a:1 b:2 c:3]

UnZip​

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

UnZip splits a sequence of pairs into two sequences.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.FromMap(map[string]int{"a": 1, "b": 2, "c": 3})
input = seq2.SortByKeys(input)

// UnZip splits a sequence into keys and values sequences
keys, values := seq2.UnZip(input)

keySlice := make([]string, 0)
for k := range keys {
keySlice = append(keySlice, k)
}
fmt.Printf("Keys: %v\n", keySlice)

valueSlice := make([]int, 0)
for v := range values {
valueSlice = append(valueSlice, v)
}
fmt.Printf("Values: %v\n", valueSlice)
}

Output

Keys: [a b c]
Values: [1 2 3]
Example (After Zip)
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq"
"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
nums := seq.Of(1, 2, 3)
letters := seq.Of("a", "b", "c")

zipped := seq.Zip(nums, letters)

unzipped1, unzipped2 := seq2.UnZip(zipped)

result1 := seq.Collect(unzipped1)
result2 := seq.Collect(unzipped2)

fmt.Println(result1)
fmt.Println(result2)
}

Output

[1 2 3]
[a b c]

Union​

func Union[K comparable, V comparable](seq1 iter.Seq2[K, V], seq2 iter.Seq2[K, V]) iter.Seq2[K, V]

Union returns a sequence that contains all distinct elements from both input sequences.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
first := seq2.FromMap(map[string]int{"a": 1, "b": 2, "c": 3})
first = seq2.SortByKeys(first)
second := seq2.FromMap(map[string]int{"c": 3, "d": 4, "e": 5})
second = seq2.SortByKeys(second)

// Union returns distinct elements from both sequences
combined := seq2.Union(first, second)

result := seq2.CollectToMap(combined)
fmt.Println(result)
}

Output

map[a:1 b:2 c:3 d:4 e:5]

UnionAll​

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

UnionAll returns a sequence that contains all elements from both input sequences.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
first := seq2.FromMap(map[string]int{"a": 1, "b": 2})
first = seq2.SortByKeys(first)
second := seq2.FromMap(map[string]int{"c": 3, "b": 2})
second = seq2.SortByKeys(second)

// UnionAll is an alias for Concat
combined := seq2.UnionAll(first, second)

result := seq2.CollectToMap(combined)
fmt.Println(result)
}

Output

map[a:1 b:2 c:3]

Uniq​

func Uniq[K comparable, V comparable](seq iter.Seq2[K, V]) iter.Seq2[K, V]

Uniq returns a new sequence that contains only the unique elements of the given sequence. It compares both key and value. In case of pointers, pointers are compared, not the values they point to.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
// Create a sequence with duplicate key-value pairs
input := seq2.Concat(
seq2.FromMap(map[string]int{"a": 1, "b": 2}),
seq2.FromMap(map[string]int{"a": 1, "c": 3}),
)

// Get unique key-value pairs
unique := seq2.Uniq(input)

result := seq2.CollectToMap(unique)
fmt.Println(result)
}

Output

map[a:1 b:2 c:3]

UniqBy​

func UniqBy[K any, V any, K2 comparable](seq iter.Seq2[K, V], mapper Mapper[K, V, K2]) iter.Seq2[K, V]

UniqBy returns a new sequence that contains only the unique elements of the given sequence based on result of the mapper.

Example
package main

import (
"fmt"
"strconv"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.FromMap(map[string]int{"apple": 1, "banana": 2, "apricot": 3, "berry": 4, "blueberry": 5})
input = seq2.SortByKeys(input)

// Get unique entries based on first letter and value modulo 2
unique := seq2.UniqBy(input, func(k string, v int) string {
return string(k[0]) + strconv.Itoa(v%2)
})

result := seq2.CollectToMap(unique)
fmt.Println(result)
}

Output

map[apple:1 banana:2 blueberry:5]

UniqByKeys​

func UniqByKeys[K any, V any, K2 comparable](seq iter.Seq2[K, V], mapper KeyMapper[K, K2]) iter.Seq2[K, V]

UniqByKeys returns a new sequence that contains only the unique elements of the given sequence based on a result of key mapper.

Example
package main

import (
"fmt"
"strings"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.FromMap(map[string]int{"Apple": 1, "apricot": 2, "Banana": 3, "berry": 4})
input = seq2.SortByKeys(input)

// Get unique entries based on lowercase first letter of key
unique := seq2.UniqByKeys(input, func(k string) string {
return strings.ToLower(string(k[0]))
})

result := seq2.CollectToMap(unique)
fmt.Println(result)
}

Output

map[Apple:1 Banana:3]

UniqByValues​

func UniqByValues[K any, V any, V2 comparable](seq iter.Seq2[K, V], mapper ValueMapper[V, V2]) iter.Seq2[K, V]

UniqByValues returns a new sequence that contains only the unique elements of the given sequence based on a result of value mapper.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.FromMap(map[string]int{"a": 10, "b": 21, "c": 30, "d": 44})
input = seq2.SortByKeys(input)

// Get unique entries based on value modulo 10
unique := seq2.UniqByValues(input, func(v int) int {
return v % 10
})

result := seq2.CollectToMap(unique)
fmt.Println(result)
}

Output

map[a:10 b:21 d:44]

UniqKeys​

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

UniqKeys returns a new sequence that contains only the elements with unique keys from the given sequence.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
// Create a sequence with duplicate keys
input := seq2.Concat(
seq2.FromMap(map[string]int{"a": 1, "b": 2}),
seq2.FromMap(map[string]int{"a": 3, "c": 4}),
)

// Get entries with unique keys (first occurrence wins)
unique := seq2.UniqKeys(input)

result := seq2.CollectToMap(unique)
fmt.Println(result)
}

Output

map[a:1 b:2 c:4]

UniqValues​

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

UniqValues returns a new sequence that contains only the elements with unique values from the given sequence.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
// Create a sequence with duplicate values
input := seq2.FromMap(map[string]int{"a": 1, "b": 2, "c": 1, "d": 3})
input = seq2.SortByKeys(input)

// Get entries with unique values (first occurrence wins)
unique := seq2.UniqValues(input)

result := seq2.CollectToMap(unique)
fmt.Println(result)
}

Output

map[a:1 b:2 d:3]

Values​

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

Values returns a sequence of values from a sequence of key-value pairs.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq"
"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.OfIndexed("a", "b", "c")

keys := seq2.Values(input)

seq.ForEach(keys, func(v string) {
fmt.Print(v, " ")
})
}

Output

a b c

Where​

func Where[K any, V any](seq iter.Seq2[K, V], predicate Predicate[K, V]) iter.Seq2[K, V]

Where returns a new sequence that contains only the elements that satisfy the predicate. SQL-like alias for Filter

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
input := seq2.FromMap(map[string]int{"a": 1, "b": 2, "c": 3, "d": 4})
input = seq2.SortByKeys(input)

// Where is an alias for Filter
filtered := seq2.Where(input, func(k string, v int) bool {
return v > 2
})

result := seq2.CollectToMap(filtered)
fmt.Println(result)
}

Output

map[c:3 d:4]

WithIndex​

func WithIndex[E any](seq iter.Seq[E]) iter.Seq2[int, E]

WithIndex creates a new indexed sequence from the given sequence.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq"
"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
// Create a iter.Seq of values
values := seq.Of("a", "b", "c")

// Add indexes
indexed := seq2.WithIndex(values)

result := seq2.CollectToMap(indexed)
fmt.Println(result)
}

Output

map[0:a 1:b 2:c]

WithoutIndex​

func WithoutIndex[E any](indexed iter.Seq2[int, E]) iter.Seq[E]

WithoutIndex creates a new sequence from the given indexed sequence.

Example
package main

import (
"fmt"

"github.com/go-softwarelab/common/pkg/seq"
"github.com/go-softwarelab/common/pkg/seq2"
)

func main() {
// Create an indexed sequence
indexed := seq2.OfIndexed("a", "b", "c")

// Remove indexes
values := seq2.WithoutIndex(indexed)

result := seq.Collect(values)
fmt.Println(result)
}

Output

[a b c]

type Consumer​

Consumer is a function that consumes an element of an iter.Seq2.

type Consumer[K any, V any] = func(K, V)

type DoubleMapper​

DoubleMapper is a function that takes an element and returns a new sequence element.

type DoubleMapper[K, V, RK, RV any] = func(K, V) (RK, RV)

type KeyMapper​

KeyMapper is a function that takes Key a new Key.

type KeyMapper[K, R any] = func(K) R

type KeyPredicate​

KeyPredicate is a function that is used to filter by key.

type KeyPredicate[E any] = KeyMapper[E, bool]

type Mapper​

Mapper is a function that takes an element and returns a new element.

type Mapper[K, V, R any] = func(K, V) R

type Predicate​

Predicate is a function that takes an element and returns a boolean.

type Predicate[K any, V any] = Mapper[K, V, bool]

type ValueMapper​

ValueMapper is a function that takes Value a new Value.

type ValueMapper[V, R any] = func(V) R

type ValuePredicate​

ValuePredicate is a function that is used to filter by value.

type ValuePredicate[E any] = ValueMapper[E, bool]