This content is for v1.1.0. Switch to the latest version for up-to-date documentation.
Filtering
Keeping some elements and dropping others — by predicate, by key, or by what has already been seen. Everything here streams: no operator on this page buffers the input, though the distinct family retains one entry per distinct key.
Filter
Section titled “Filter”func (s Seq[T]) Filter(pred func(T) bool) Seq[T]Filter yields the elements for which pred returns true.
fmt.Println(catena.Of(1, 2, 3, 4, 5). Filter(func(n int) bool { return n%2 == 0 }). Collect())[2 4]FilterNot
Section titled “FilterNot”func (s Seq[T]) FilterNot(pred func(T) bool) Seq[T]FilterNot yields the elements for which pred returns false.
// The negated form, for when the predicate reads better positively.fmt.Println(catena.Of("go", "", "rust", "", "zig"). FilterNot(func(s string) bool { return s == "" }). Collect())[go rust zig]FilterIndexed
Section titled “FilterIndexed”func (s Seq[T]) FilterIndexed(pred func(int, T) bool) Seq[T]FilterIndexed yields the elements for which pred(index, element) returns true. The index counts source elements from 0.
// The index counts source elements, not surviving ones.fmt.Println(catena.Of("a", "b", "c", "d", "e"). FilterIndexed(func(i int, _ string) bool { return i%2 == 0 }). Collect())[a c e]FilterErr
Section titled “FilterErr”func (s Seq[T]) FilterErr(pred func(T) (bool, error)) Try[T]FilterErr yields elements pred admits, as a Try; a failed pred call yields (zero, err).
// A predicate that can fail produces a Try, so the caller chooses// what a failure means rather than the pipeline deciding.ports := catena.Of("80", "443", "https", "8080")valid := ports.FilterErr(func(s string) (bool, error) { if strings.ContainsAny(s, "abcdefghijklmnopqrstuvwxyz") { return false, fmt.Errorf("not a port: %q", s) } return len(s) > 2, nil})
kept, errs := valid.CollectAll()fmt.Println(kept, errs)[443 8080] [not a port: "https"]Distinct
Section titled “Distinct”func Distinct[T comparable](s Seq[T]) Seq[T]Distinct yields elements not seen before; the first occurrence wins.
// Distinct constrains the element type, so it is a package function// rather than a method — a method on Seq[T any] may require nothing// of T. First occurrence wins, and encounter order is preserved.fmt.Println(catena.Distinct(catena.Of(3, 1, 3, 2, 1)).Collect())[3 1 2]DistinctBy
Section titled “DistinctBy”func (s Seq[T]) DistinctBy[K comparable](sel func(T) K) Seq[T]DistinctBy yields elements whose key has not been seen before; the first occurrence wins.
type user struct { Org, Name string}users := catena.Of( user{"acme", "ada"}, user{"globex", "bob"}, user{"acme", "eve"},)
// One user per org; the first occurrence wins.fmt.Println(users. DistinctBy(func(u user) string { return u.Org }). Collect())[{acme ada} {globex bob}]DistinctWith
Section titled “DistinctWith”func (s Seq[T]) DistinctWith(eq func(a, b T) bool) Seq[T]DistinctWith yields elements no earlier element equals under eq. First occurrence wins.
// For keys that are not comparable, or an equality of your own.// Retains every distinct element and compares against all of them,// so this is for small inputs.fmt.Println(catena.Of("Go", "GO", "rust", "go"). DistinctWith(strings.EqualFold). Collect())[Go rust]Dedupe
Section titled “Dedupe”func Dedupe[T comparable](s Seq[T]) Seq[T]Dedupe yields elements that differ from their predecessor — consecutive duplicates only, O(1) memory.
// Consecutive duplicates only. On sorted input it equals Distinct at// a fraction of the cost; on unsorted input the two differ.fmt.Println(catena.Dedupe(catena.Of(3, 3, 1, 1, 3)).Collect())[3 1 3]DedupeBy
Section titled “DedupeBy”func (s Seq[T]) DedupeBy[K comparable](sel func(T) K) Seq[T]DedupeBy yields elements whose key differs from the previous element’s key — consecutive duplicates only, O(1) memory. On key-sorted input it equals DistinctBy at a fraction of the cost.
// Collapses CONSECUTIVE runs only, in O(1) memory — the streaming// alternative to DistinctBy, and the right choice on an unbounded// source where a seen-set would grow forever.type reading struct { Tick int Zone string}readings := catena.Of( reading{1, "cold"}, reading{2, "cold"}, reading{3, "warm"}, reading{4, "cold"},)
fmt.Println(readings. DedupeBy(func(r reading) string { return r.Zone }). Collect())[{1 cold} {3 warm} {4 cold}]NonZero
Section titled “NonZero”func NonZero[T comparable](s Seq[T]) Seq[T]NonZero yields the elements that are not the zero value of T.
// Drops the zero value of T — empty strings here, but equally 0,// nil pointers, or a zero struct.fmt.Println(catena.NonZero(catena.Of("go", "", "rust", "")).Collect())[go rust]