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.
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)
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](seq 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]