seq

package module
v0.1.2 Latest Latest
Warning

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

Go to latest
Published: Nov 15, 2025 License: MIT Imports: 2 Imported by: 0

README

seq

import "github.com/banky/seq"

Package seq provides generic helpers for working with slices and other sequences. It includes several functions that are not included in the standard library for working with slices which I have found helpful. It includes functions for mapping, filtering, grouping, chunking, de-duplicating, and computing aggregate values such as minima and maxima.

Index

func Chunk

func Chunk[T any](slice []T, size int) [][]T

Chunk splits slice into consecutive sub-slices of at most size elements. The final chunk may be smaller than size. The caller must ensure size > 0.

Example

package main

import (
	"fmt"

	"github.com/banky/seq"
)

func main() {
	values := []int{1, 2, 3, 4, 5}
	chunks := seq.Chunk(values, 2)
	fmt.Println(chunks)
}
Output
[[1 2] [3 4] [5]]

func Filter

func Filter[T any](slice []T, keep func(T) bool) []T

Filter returns a new slice containing only the elements of slice for which keep returns true.

Example

package main

import (
	"fmt"

	"github.com/banky/seq"
)

func main() {
	numbers := []int{1, 2, 3, 4, 5, 6}
	evens := seq.Filter(numbers, func(n int) bool { return n%2 == 0 })
	fmt.Println(evens)
}
Output
[2 4 6]

func Flatten

func Flatten[T any](slices [][]T) []T

Flatten returns a new slice containing all the elements of slices flattened into a single slice.

Example

package main

import (
	"fmt"

	"github.com/banky/seq"
)

func main() {
	nested := [][]int{{1, 2}, {}, {3}, {4, 5}}
	flat := seq.Flatten(nested)
	fmt.Println(flat)
}
Output
[1 2 3 4 5]

func GroupBy

func GroupBy[T any, K comparable](slice []T, keyFunc func(T) K) map[K][]T

GroupBy groups the elements of slice into a map keyed by the value returned from keyFunc for each element.

Example

package main

import (
	"fmt"

	"github.com/banky/seq"
)

func main() {
	words := []string{"a", "bb", "ccc", "dd", "e"}
	byLen := seq.GroupBy(words, func(s string) int { return len(s) })

	// Print groups in length order for stable output.
	fmt.Println(byLen[1])
	fmt.Println(byLen[2])
	fmt.Println(byLen[3])
}
Output
[a e]
[bb dd]
[ccc]

func LastIndex

func LastIndex[T comparable](slice []T, v T) (idx int, ok bool)

LastIndex returns the index of the last occurrence of v in slice. If v is not found, the returned index is -1 and ok is false.

Example

package main

import (
	"fmt"

	"github.com/banky/seq"
)

func main() {
	values := []string{"a", "b", "c", "b"}
	idx, ok := seq.LastIndex(values, "b")
	fmt.Println(idx, ok)

	_, ok = seq.LastIndex(values, "z")
	fmt.Println(ok)
}
Output
3 true
false

func Map

func Map[T any, R any](slice []T, f func(T) R) []R

Map returns a new slice containing the results of applying f to each element of slice.

Example

package main

import (
	"fmt"

	"github.com/banky/seq"
)

func main() {
	numbers := []int{1, 2, 3}
	strs := seq.Map(numbers, func(n int) string { return fmt.Sprintf("n=%d", n) })
	fmt.Println(strs)
}
Output
[n=1 n=2 n=3]

func MinMax

func MinMax[T cmp.Ordered](slice []T) (min, max T)

MinMax returns the minimum and maximum values of slice. The caller must ensure that slice is non-empty otherwise MinMax will panic.

Example

package main

import (
	"fmt"

	"github.com/banky/seq"
)

func main() {
	values := []int{5, 2, 9, 1}
	min, max := seq.MinMax(values)
	fmt.Println(min, max)
}
Output
1 9

func MinMaxFunc

func MinMaxFunc[T any](slice []T, less func(T, T) int) (min, max T)

MinMaxFunc returns the minimum and maximum values of slice using the comparison function less. The comparison function should return a negative value if a < b, zero if a == b, and a positive value if a > b. The caller must ensure that slice is non-empty otherwise MinMaxFunc will panic.

Example

package main

import (
	"fmt"

	"github.com/banky/seq"
)

func main() {
	type Person struct {
		Name string
		Age  int
	}

	people := []Person{
		{Name: "Alice", Age: 30},
		{Name: "Bob", Age: 25},
		{Name: "Charlie", Age: 40},
	}

	less := func(a, b Person) int {
		return compare(a.Age, b.Age)
	}

	min, max := seq.MinMaxFunc(people, less)
	fmt.Println(min, max)
}

// helper — replaces cmp.Compare but avoids extra imports
func compare(a, b int) int {
	switch {
	case a < b:
		return -1
	case a > b:
		return 1
	default:
		return 0
	}
}
Output
{Bob 25} {Charlie 40}

func Partition

func Partition[T any](slice []T, pred func(T) bool) (matches, nonMatches []T)

Partition splits slice into two slices: matches, containing elements for which pred returns true, and nonMatches, containing the rest.

Example

package main

import (
	"fmt"

	"github.com/banky/seq"
)

func main() {
	numbers := []int{1, 2, 3, 4, 5, 6}
	evens, odds := seq.Partition(numbers, func(n int) bool { return n%2 == 0 })
	fmt.Println(evens, odds)
}
Output
[2 4 6] [1 3 5]

func Reduce

func Reduce[T any, R any](slice []T, init R, f func(R, T) R) R

Reduce applies f to each element of slice, accumulating the result, and returns the final accumulated value. The accumulator is initialized with init.

Example

package main

import (
	"fmt"

	"github.com/banky/seq"
)

func main() {
	numbers := []int{1, 2, 3, 4}
	sum := seq.Reduce(numbers, 0, func(acc, n int) int { return acc + n })
	fmt.Println(sum)
}
Output
10

func Unique

func Unique[T comparable](slice []T) []T

Unique returns a new slice containing only the unique elements of slice. The order of first occurrence is preserved.

Example

package main

import (
	"fmt"

	"github.com/banky/seq"
)

func main() {
	values := []int{1, 2, 1, 3, 2, 4, 4}
	uniq := seq.Unique(values)
	fmt.Println(uniq)
}
Output
[1 2 3 4]

func UniqueBy

func UniqueBy[T any, K comparable](slice []T, keyFunc func(T) K) []T

UniqueBy returns a new slice containing only the unique elements of slice, where uniqueness is determined by the key returned from keyFunc. The order of first occurrence (by key) is preserved.

Example

package main

import (
	"fmt"

	"github.com/banky/seq"
)

func main() {
	type User struct {
		Name  string
		Email string
	}

	users := []User{
		{Name: "Alice", Email: "[email protected]"},
		{Name: "Bob", Email: "[email protected]"},
		{Name: "Alice Clone", Email: "[email protected]"},
	}

	uniq := seq.UniqueBy(users, func(u User) string { return u.Email })
	fmt.Println(uniq)
}
Output
[{Alice [email protected]} {Bob [email protected]}]

Generated by gomarkdoc

Documentation

Overview

Package seq provides generic helpers for working with slices and other sequences. It includes several functions that are not included in the standard library for working with slices which I have found helpful. It includes functions for mapping, filtering, grouping, chunking, de-duplicating, and computing aggregate values such as minima and maxima.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Chunk

func Chunk[T any](slice []T, size int) [][]T

Chunk splits slice into consecutive sub-slices of at most size elements. The final chunk may be smaller than size. The caller must ensure size > 0.

Example
package main

import (
	"fmt"

	"github.com/banky/seq"
)

func main() {
	values := []int{1, 2, 3, 4, 5}
	chunks := seq.Chunk(values, 2)
	fmt.Println(chunks)
}
Output:

[[1 2] [3 4] [5]]

func Filter

func Filter[T any](slice []T, keep func(T) bool) []T

Filter returns a new slice containing only the elements of slice for which keep returns true.

Example
package main

import (
	"fmt"

	"github.com/banky/seq"
)

func main() {
	numbers := []int{1, 2, 3, 4, 5, 6}
	evens := seq.Filter(numbers, func(n int) bool { return n%2 == 0 })
	fmt.Println(evens)
}
Output:

[2 4 6]

func Flatten

func Flatten[T any](slices [][]T) []T

Flatten returns a new slice containing all the elements of slices flattened into a single slice.

Example
package main

import (
	"fmt"

	"github.com/banky/seq"
)

func main() {
	nested := [][]int{{1, 2}, {}, {3}, {4, 5}}
	flat := seq.Flatten(nested)
	fmt.Println(flat)
}
Output:

[1 2 3 4 5]

func GroupBy

func GroupBy[T any, K comparable](slice []T, keyFunc func(T) K) map[K][]T

GroupBy groups the elements of slice into a map keyed by the value returned from keyFunc for each element.

Example
package main

import (
	"fmt"

	"github.com/banky/seq"
)

func main() {
	words := []string{"a", "bb", "ccc", "dd", "e"}
	byLen := seq.GroupBy(words, func(s string) int { return len(s) })

	// Print groups in length order for stable output.
	fmt.Println(byLen[1])
	fmt.Println(byLen[2])
	fmt.Println(byLen[3])
}
Output:

[a e]
[bb dd]
[ccc]

func LastIndex

func LastIndex[T comparable](slice []T, v T) (idx int, ok bool)

LastIndex returns the index of the last occurrence of v in slice. If v is not found, the returned index is -1 and ok is false.

Example
package main

import (
	"fmt"

	"github.com/banky/seq"
)

func main() {
	values := []string{"a", "b", "c", "b"}
	idx, ok := seq.LastIndex(values, "b")
	fmt.Println(idx, ok)

	_, ok = seq.LastIndex(values, "z")
	fmt.Println(ok)
}
Output:

3 true
false

func Map

func Map[T any, R any](slice []T, f func(T) R) []R

Map returns a new slice containing the results of applying f to each element of slice.

Example
package main

import (
	"fmt"

	"github.com/banky/seq"
)

func main() {
	numbers := []int{1, 2, 3}
	strs := seq.Map(numbers, func(n int) string { return fmt.Sprintf("n=%d", n) })
	fmt.Println(strs)
}
Output:

[n=1 n=2 n=3]

func MinMax

func MinMax[T cmp.Ordered](slice []T) (min, max T)

MinMax returns the minimum and maximum values of slice. The caller must ensure that slice is non-empty otherwise MinMax will panic.

Example
package main

import (
	"fmt"

	"github.com/banky/seq"
)

func main() {
	values := []int{5, 2, 9, 1}
	min, max := seq.MinMax(values)
	fmt.Println(min, max)
}
Output:

1 9

func MinMaxFunc

func MinMaxFunc[T any](slice []T, less func(T, T) int) (min, max T)

MinMaxFunc returns the minimum and maximum values of slice using the comparison function less. The comparison function should return a negative value if a < b, zero if a == b, and a positive value if a > b. The caller must ensure that slice is non-empty otherwise MinMaxFunc will panic.

Example
package main

import (
	"fmt"

	"github.com/banky/seq"
)

func main() {
	type Person struct {
		Name string
		Age  int
	}

	people := []Person{
		{Name: "Alice", Age: 30},
		{Name: "Bob", Age: 25},
		{Name: "Charlie", Age: 40},
	}

	less := func(a, b Person) int {
		return compare(a.Age, b.Age)
	}

	min, max := seq.MinMaxFunc(people, less)
	fmt.Println(min, max)
}

// helper — replaces cmp.Compare but avoids extra imports
func compare(a, b int) int {
	switch {
	case a < b:
		return -1
	case a > b:
		return 1
	default:
		return 0
	}
}
Output:

{Bob 25} {Charlie 40}

func Partition

func Partition[T any](slice []T, pred func(T) bool) (matches, nonMatches []T)

Partition splits slice into two slices: matches, containing elements for which pred returns true, and nonMatches, containing the rest.

Example
package main

import (
	"fmt"

	"github.com/banky/seq"
)

func main() {
	numbers := []int{1, 2, 3, 4, 5, 6}
	evens, odds := seq.Partition(numbers, func(n int) bool { return n%2 == 0 })
	fmt.Println(evens, odds)
}
Output:

[2 4 6] [1 3 5]

func Reduce

func Reduce[T any, R any](slice []T, init R, f func(R, T) R) R

Reduce applies f to each element of slice, accumulating the result, and returns the final accumulated value. The accumulator is initialized with init.

Example
package main

import (
	"fmt"

	"github.com/banky/seq"
)

func main() {
	numbers := []int{1, 2, 3, 4}
	sum := seq.Reduce(numbers, 0, func(acc, n int) int { return acc + n })
	fmt.Println(sum)
}
Output:

10

func Unique

func Unique[T comparable](slice []T) []T

Unique returns a new slice containing only the unique elements of slice. The order of first occurrence is preserved.

Example
package main

import (
	"fmt"

	"github.com/banky/seq"
)

func main() {
	values := []int{1, 2, 1, 3, 2, 4, 4}
	uniq := seq.Unique(values)
	fmt.Println(uniq)
}
Output:

[1 2 3 4]

func UniqueBy

func UniqueBy[T any, K comparable](slice []T, keyFunc func(T) K) []T

UniqueBy returns a new slice containing only the unique elements of slice, where uniqueness is determined by the key returned from keyFunc. The order of first occurrence (by key) is preserved.

Example
package main

import (
	"fmt"

	"github.com/banky/seq"
)

func main() {
	type User struct {
		Name  string
		Email string
	}

	users := []User{
		{Name: "Alice", Email: "[email protected]"},
		{Name: "Bob", Email: "[email protected]"},
		{Name: "Alice Clone", Email: "[email protected]"},
	}

	uniq := seq.UniqueBy(users, func(u User) string { return u.Email })
	fmt.Println(uniq)
}
Output:

[{Alice [email protected]} {Bob [email protected]}]

Types

This section is empty.

Jump to

Keyboard shortcuts

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