list

package module
v0.2.1 Latest Latest
Warning

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

Go to latest
Published: Apr 5, 2026 License: MIT Imports: 3 Imported by: 0

README ยถ

list

Go Reference Build Go Version Coverage

The list operations Go's stdlib leaves out โ€” set algebra, positional extraction, sampling, reordering, sorting, and substitution โ€” as plain generic functions on []T.

Go's slices package covers sort, search, and mutation of contiguous ranges. It deliberately omits true deduplication, set algebra across multiple slices, positional range extraction with safe bounds, random sampling, reordering, and value-based substitution โ€” the operations you reach for when shaping a slice rather than searching or sorting it in place. list provides those operations as one family of outcome-named functions, in one repo, so you don't have to compose three libraries to express a single pipeline.

// Deduplicate while preserving order of first occurrence
unique := list.Unique(tags)

// Take the first 10, then sort them ascending, then drop zero values
top := list.Compact(list.Sort(list.FirstN(entries, 10)))

// Sample 5 random users without replacement
sample := list.SampleN(users, 5)

// Merge two cohorts, drop the banned set, sort by signup date
active := list.SortBy(
    list.Minus(list.Union(admins, editors), banned),
    func(a, b User) int { return a.SignedUp.Compare(b.SignedUp) },
)

โœจ Why list?

Set operations (comparable):

  • ๐Ÿงน Unique is true dedup โ€” preserves order of first occurrence, unlike slices.Compact which only removes consecutive duplicates
  • ๐Ÿ”— Union across N slices โ€” variadic, returns unique elements in first-seen order
  • โšก Intersect across N slices โ€” variadic, elements present in every slice
  • โž– Minus for binary difference โ€” list.Minus(allUsers, banned) reads like English
  • โ‡„ SymmetricDifference โ€” elements in either slice but not both
  • ๐Ÿšซ Without removes specific values โ€” not a set operation, just "drop these elements"

Positional (any) โ€” safe on out-of-range without panics:

  • ๐Ÿ” FirstN / LastN โ€” take the head or tail, clamped to length
  • ๐Ÿ“ Between(s, start, end) โ€” like s[start:end] but bounds-clamped, never panics
  • ๐ŸŽฏ At(s, i) โ€” single-element access with negative indexes (At(s, -1) is the last), returns (T, bool)
  • First / Last โ€” aliases for At(s, 0) / At(s, -1)

Sampling (any):

  • ๐ŸŽฒ Sample / SampleN โ€” uniformly random selection via math/rand/v2

Reordering (any):

  • โ†ฉ๏ธ Reverse โ€” new reversed slice, input untouched
  • ๐Ÿ”€ Shuffle โ€” new randomly-permuted slice, input untouched

Sorting:

  • ๐Ÿ“Š Sort / SortDesc (cmp.Ordered) โ€” new sorted slice, ascending or descending. NaN sorts first ascending, last descending.
  • ๐Ÿงฎ SortBy (any) โ€” new sorted slice with a caller-supplied func(a, b T) int comparator for non-ordered types

Zero stripping (comparable):

  • โœจ Compact โ€” new slice with every element equal to T's zero value removed. (Distinct from stdlib slices.Compact, which removes consecutive duplicates.)

Substitution (comparable):

  • ๐Ÿ” Replace / ReplaceFirst โ€” value-based replacement, all occurrences or first only

Contracts for everything:

  • ๐Ÿ›ก๏ธ Order-preserving โ€” every operation has a defined, stable output order
  • ๐Ÿชถ Zero dependencies โ€” pure Go stdlib; math/rand/v2 for sampling, slices for the sort primitives
  • ๐Ÿ”’ Never panics on valid input โ€” nil, empty, out-of-range all return empty (non-nil) slices or (_, false)
  • ๐ŸงŠ Immutable โ€” no function mutates its input; every result is a fresh allocation

๐Ÿ“ฆ Installation

go get github.com/bold-minds/list

Requires Go 1.23 or later.

๐Ÿš€ Quick Start

package main

import (
    "fmt"

    "github.com/bold-minds/list"
)

func main() {
    tags := []string{"go", "web", "api", "go", "web", "auth"}
    admins := []int{1, 2, 3, 4}
    editors := []int{3, 4, 5, 6}
    banned := []int{2, 5}

    // Deduplicate, preserve order of first occurrence
    unique := list.Unique(tags)
    fmt.Println(unique) // [go web api auth]

    // Combine slices, unique across all
    all := list.Union(admins, editors)
    fmt.Println(all) // [1 2 3 4 5 6]

    // Elements present in all input slices
    both := list.Intersect(admins, editors)
    fmt.Println(both) // [3 4]

    // Elements in the first slice but not in the second
    adminsOnly := list.Minus(admins, editors)
    fmt.Println(adminsOnly) // [1 2]

    // Remove specific values
    allowed := list.Without(admins, 2, 4)
    fmt.Println(allowed) // [1 3]

    // Compose them when needed
    activeAdmins := list.Minus(list.Union(admins, editors), banned)
    fmt.Println(activeAdmins) // [1 3 4 6]
}

๐Ÿ”ง Core Features

Unique โ€” true deduplication

Returns a new slice containing each unique value from the input, in order of first occurrence. Unlike slices.Compact (which only removes consecutive duplicates), Unique handles duplicates anywhere in the slice without requiring a sort first.

list.Unique([]int{1, 2, 2, 3, 1, 4, 2})  // [1 2 3 4]
list.Unique([]string{"go", "web", "go"}) // [go web]
list.Unique([]int{})                     // []

Works with any comparable type: primitives, pointers, interfaces, and structs whose fields are comparable.

Union โ€” unique across N slices

Returns the unique elements across all provided slices, preserving order of first occurrence as you walk through the inputs.

list.Union([]int{1, 2, 3}, []int{3, 4, 5})             // [1 2 3 4 5]
list.Union([]int{1}, []int{2}, []int{1, 3})            // [1 2 3]
list.Union([]string{"a", "b"}, []string{"b", "c"})     // [a b c]
list.Union[int]()                                      // []

Variadic โ€” works with any number of input slices (including zero, which returns an empty slice).

Intersect โ€” elements in every slice

Returns the unique elements that appear in every provided slice. Order is taken from the first input slice.

list.Intersect([]int{1, 2, 3, 4}, []int{2, 3, 5})          // [2 3]
list.Intersect([]int{1, 2, 3}, []int{2, 3}, []int{3, 4})   // [3]
list.Intersect[int]([]int{1, 2, 3})                        // [1 2 3]
list.Intersect[int]()                                      // []

Variadic, matching Union. A single-slice call returns the slice's unique elements (equivalent to Unique).

Minus โ€” binary set difference

Returns the unique elements of the first slice that are not present in the second slice. Order is taken from the first slice.

list.Minus([]int{1, 2, 3, 4}, []int{2, 4})        // [1 3]
list.Minus([]string{"a", "b", "c"}, []string{"b"}) // [a c]
list.Minus([]int{1, 2, 3}, []int{})               // [1 2 3]
list.Minus([]int{}, []int{1, 2})                  // []

Binary (always exactly two arguments) because "subtract multiple slices" is ambiguous โ€” is it a โˆ’ (b โˆช c) or ((a โˆ’ b) โˆ’ c)? If you need to subtract multiple, compose with Union: list.Minus(a, list.Union(b, c, d)).

Without โ€” remove specific values

Returns a new slice with all occurrences of the specified values removed, preserving the order of remaining elements.

list.Without([]int{1, 2, 3, 2, 1}, 2)             // [1 3 1]
list.Without([]string{"a", "b", "c"}, "b", "c")   // [a]
list.Without([]int{1, 2, 3}, 5)                   // [1 2 3]

Without does not deduplicate remaining elements โ€” if 1 appears three times in the input and you don't remove 1, it appears three times in the output. For dedup + removal, chain: list.Unique(list.Without(s, v)).

FirstN / LastN / Between โ€” positional ranges, bounds-clamped

Out-of-range indexes clamp rather than panic. Negative counts become empty slices. Over-large counts return the whole (copied) slice.

s := []int{10, 20, 30, 40, 50}

list.FirstN(s, 3)           // [10 20 30]
list.FirstN(s, 100)         // [10 20 30 40 50]  (clamped, not out-of-range)
list.FirstN(s, 0)           // []
list.LastN(s, 2)            // [40 50]
list.Between(s, 1, 4)       // [20 30 40]
list.Between(s, -10, 100)   // [10 20 30 40 50]  (both bounds clamped)
list.Between(s, 4, 2)       // []                (inverted range)

Between is the non-panicking replacement for s[start:end] when indexes come from user input, config, or any source where out-of-range is a possibility rather than a bug.

At / First / Last โ€” single-element access with negative-index support

Returns (value, ok) โ€” ok is false for empty slices or out-of-range indexes. Negative indexes count from the end, so At(s, -1) is the last element.

s := []string{"a", "b", "c"}

v, ok := list.At(s, 0)       // ("a", true)
v, ok  = list.At(s, -1)      // ("c", true)
v, ok  = list.At(s, 99)      // ("", false)
v, ok  = list.First(s)       // ("a", true)
v, ok  = list.Last(s)        // ("c", true)

Use At when you want to extract a single element defensively without the if i < len(s) { โ€ฆ } guard at every call site.

Sample / SampleN โ€” random selection

Sample returns one uniformly-random element; SampleN returns n distinct random elements (without replacement) via a Fisherโ€“Yates partial shuffle.

users := []User{ /* ... */ }

u, ok := list.Sample(users)          // one random user
five := list.SampleN(users, 5)       // 5 distinct random users
all  := list.SampleN(users, 1000)    // full shuffle if n >= len

Uses math/rand/v2's goroutine-safe top-level source. Not cryptographically secure โ€” fine for tests, fixtures, A/B bucket assignment, and UI randomization; use crypto/rand directly if you need unpredictability guarantees.

Reverse / Shuffle โ€” reordering without a key

Both return a new slice; the input is untouched.

list.Reverse([]int{1, 2, 3})  // [3 2 1]
list.Shuffle(users)           // users in random order, input untouched
Sort / SortDesc / SortBy โ€” non-mutating sort

Unlike stdlib slices.Sort which sorts in place, list.Sort returns a fresh sorted slice. The input is never touched โ€” the same guarantee as every other list function.

// Ordered types: cmp.Ordered constraint covers strings, all integer
// widths, and both float types.
list.Sort([]int{3, 1, 2})            // [1 2 3]
list.Sort([]string{"c", "a", "b"})   // [a b c]
list.SortDesc([]int{3, 1, 2})        // [3 2 1]

// Non-ordered types: supply a comparator.
users := []User{ /* ... */ }
byName := list.SortBy(users, func(a, b User) int {
    return strings.Compare(a.Name, b.Name)
})

NaN sorts before every non-NaN value under Sort (and after under SortDesc), following cmp.Compare's defined behavior.

Compact โ€” strip zero values

Returns a new slice with every element equal to T's zero value removed. This is distinct from stdlib slices.Compact, which removes consecutive duplicates regardless of value โ€” the naming collision is unfortunate but irreversible.

list.Compact([]string{"a", "", "b", "", "c"})  // [a b c]
list.Compact([]int{1, 0, 2, 0, 3})             // [1 2 3]
list.Compact([]*User{u1, nil, u2, nil})        // [u1 u2]

Requires T comparable so the zero value can be detected without reflection.

Replace / ReplaceFirst โ€” value-based substitution
list.Replace([]int{1, 2, 3, 2, 1}, 2, 99)         // [1 99 3 99 1]
list.ReplaceFirst([]int{1, 2, 3, 2, 1}, 2, 99)    // [1 99 3 2 1]

Positional replacement (s[i] = v) is already a one-liner in Go, so list does not ship an indexed variant.

๐Ÿ›ก๏ธ Safety guarantees

  • Never panics on valid input. Nil slices, empty slices, and zero-variadic calls all return empty (non-nil) slices.
  • Immutable. list never modifies input slices. Every function returns a new slice.
  • Order-preserving. Every operation has a defined, stable output order.
  • Non-nil results. Every function returns an empty (non-nil) slice rather than nil when there are no results. Safe to range over without nil checks.
  • Zero dependencies. Pure stdlib underneath.
NaN semantics

Floating-point NaN values follow Go's map-key semantics: NaN is never equal to NaN (including itself). This means list operations do not dedupe, intersect, or exclude NaNs:

nan := math.NaN()
list.Unique([]float64{nan, nan, nan})       // [NaN NaN NaN] โ€” all three remain
list.Minus([]float64{nan, 1.0}, []float64{nan}) // [NaN 1.0] โ€” NaN not removed

If you need NaN-aware set operations, pre-process the slice to replace NaNs with a canonical marker.

Non-comparable interface values

Go's comparable constraint is checked at compile time, but interface types can carry dynamic values whose concrete type is not comparable (e.g., a []int stored in an any). Comparing such values causes a runtime panic. list does not recover from these panics โ€” it is the caller's responsibility to ensure interface slices contain only comparable dynamic values.

๐ŸŽ๏ธ Performance

Measured on Go 1.26 (Intel Ultra 9 275HX; library targets Go 1.23+). All operations are O(n) in total input size.

BenchmarkUnique_Small-24             2087532    279.4 ns/op    408 B/op    4 allocs/op
BenchmarkUnique_WithDupes-24         2009478    287.8 ns/op    744 B/op    4 allocs/op
BenchmarkUnion_Two-24                1300902    477.7 ns/op    520 B/op    5 allocs/op
BenchmarkUnion_Three-24               593526    892.6 ns/op   1384 B/op    8 allocs/op
BenchmarkIntersect_Two-24             562664   1012 ns/op     1048 B/op   10 allocs/op
BenchmarkIntersect_Three-24           615122   1056 ns/op     1008 B/op   10 allocs/op
BenchmarkMinus_Basic-24              1402407    428.3 ns/op    736 B/op    7 allocs/op
BenchmarkWithout_SingleItem-24       9485799     61.2 ns/op     80 B/op    1 allocs/op
BenchmarkWithout_MultipleItems-24    6966316     91.9 ns/op     80 B/op    1 allocs/op

Allocations come from the map-backed lookups (unavoidable for O(1) set membership) and the result slice. Without is the cheapest because its "exclude these items" semantic does not require a dedup pass.

๐Ÿงช Testing

go test ./...                      # unit tests
go test -race ./...                # race detection
go test -bench=. -benchmem ./...   # benchmarks

Current coverage: 100%.

๐Ÿ“š API Reference

// =========================================================================
// Set operations (T comparable)
// =========================================================================

// Unique returns a new slice with duplicate elements removed, preserving
// order of first occurrence.
func Unique[T comparable](s []T) []T

// Union returns the unique elements across all provided slices,
// preserving order of first occurrence as each slice is walked in turn.
func Union[T comparable](slices ...[]T) []T

// Intersect returns the unique elements present in every provided slice.
// Order is taken from the first slice.
func Intersect[T comparable](slices ...[]T) []T

// SymmetricDifference returns unique elements present in a or b but
// not both. Order is taken from a first, then b.
func SymmetricDifference[T comparable](a, b []T) []T

// Minus returns the unique elements of a that are not present in b.
// Binary โ€” for multi-slice subtraction, compose with Union.
func Minus[T comparable](a, b []T) []T

// Without returns a new slice with all occurrences of the specified
// items removed. Does NOT deduplicate remaining elements.
func Without[T comparable](s []T, items ...T) []T

// =========================================================================
// Positional extraction (T any)
// =========================================================================

// FirstN returns the first n elements, clamped to valid range.
func FirstN[T any](s []T, n int) []T

// LastN returns the last n elements, clamped to valid range.
func LastN[T any](s []T, n int) []T

// Between returns s[start:end] with bounds clamped. Never panics.
func Between[T any](s []T, start, end int) []T

// At returns the element at index i with ok=true, or (zero, false)
// on empty slice or out-of-range. Negative indexes count from the end.
func At[T any](s []T, i int) (T, bool)

// First is an alias for At(s, 0).
func First[T any](s []T) (T, bool)

// Last is an alias for At(s, -1).
func Last[T any](s []T) (T, bool)

// =========================================================================
// Sampling (T any)
// =========================================================================

// Sample returns one uniformly-random element via math/rand/v2.
func Sample[T any](s []T) (T, bool)

// SampleN returns n distinct random elements without replacement.
func SampleN[T any](s []T, n int) []T

// =========================================================================
// Reordering (T any)
// =========================================================================

// Reverse returns a new slice in reverse order. Input not mutated.
func Reverse[T any](s []T) []T

// Shuffle returns a new randomly-permuted slice. Input not mutated.
func Shuffle[T any](s []T) []T

// =========================================================================
// Sorting
// =========================================================================

// Sort returns a new slice sorted ascending. T must be cmp.Ordered.
// Input not mutated.
func Sort[T cmp.Ordered](s []T) []T

// SortDesc returns a new slice sorted descending. T must be cmp.Ordered.
func SortDesc[T cmp.Ordered](s []T) []T

// SortBy returns a new slice sorted by a caller-supplied comparator.
// T is any; less must return negative/zero/positive for a<b / a==b / a>b.
func SortBy[T any](s []T, less func(a, b T) int) []T

// =========================================================================
// Zero stripping (T comparable)
// =========================================================================

// Compact returns a new slice with zero values of T removed.
// Distinct from stdlib slices.Compact, which removes consecutive duplicates.
func Compact[T comparable](s []T) []T

// =========================================================================
// Substitution (T comparable)
// =========================================================================

// Replace returns a new slice with every occurrence of old replaced.
func Replace[T comparable](s []T, old, newVal T) []T

// ReplaceFirst returns a new slice with the first occurrence of old replaced.
func ReplaceFirst[T comparable](s []T, old, newVal T) []T

๐Ÿค Contributing

See CONTRIBUTING.md. Bold Minds Go libraries follow a shared set of design principles; read PRINCIPLES.md before opening a PR.

๐Ÿ“„ License

MIT. See LICENSE.

  • Go standard library slices โ€” covers sort, reverse, contains, index, delete, concat. Note: slices.Compact only removes consecutive duplicates; for true deduplication, use list.Unique. The naming similarity between Compact and Unique is a known source of confusion.
  • bold-minds/each โ€” predicate and key-function operations on Go slices (Find, Filter, GroupBy, KeyBy, Partition, Count, Every). each handles per-element predicates on a single slice; list handles set semantics across one or more slices.
  • samber/lo โ€” comprehensive Go utility library. Includes Uniq, Union, Intersect, Difference, and Without among ~200 other helpers. list is the scoped version that ships only the five set operations and nothing else.

Documentation ยถ

Overview ยถ

Package list provides the list operations Go's stdlib leaves out โ€” set algebra, positional extraction, sampling, reordering, sorting, and substitution โ€” as plain generic functions on []T.

Categories ยถ

Set operations (T comparable): Unique, Union, Intersect, SymmetricDifference, Minus, Without. Treat slices as sets with predictable, stable output ordering.

Positional extraction (T any): FirstN, LastN, Between, At, First, Last. Extract by index or range. Negative indexes count from the end where meaningful; out-of-range indexes clamp or return (_, false) rather than panicking.

Sampling (T any): Sample, SampleN. Random element selection from math/rand/v2. Use crypto/rand directly if you need cryptographic entropy.

Reordering (T any): Reverse, Shuffle. Return new slices โ€” input is never mutated.

Sorting: Sort and SortDesc (T cmp.Ordered) for strings, numbers, and named types with ordered underlying kinds. SortBy (T any) for anything else via a caller-supplied comparator.

Zero stripping (T comparable): Compact. Removes every element equal to T's zero value.

Substitution (T comparable): Replace, ReplaceFirst. Value-based replacement; replace-by-index is intentionally a one-liner (s[i] = v) and not exposed.

Contracts ยถ

Every operation is nil-safe, never panics on nil or empty input, and never mutates its input. Empty results are returned as non-nil empty slices, so callers can range over them without nil checks.

All functions are safe for concurrent use on shared inputs: they never mutate their arguments, so multiple goroutines may call any function with overlapping or identical input slices without external synchronization. Each call allocates its own result slice, so callers may freely mutate the returned slice without affecting inputs or other callers' results.

NaN semantics for set operations ยถ

Float64 and float32 values follow Go's map-key semantics: NaN is never equal to NaN (including itself), so each NaN is a distinct map key. This has consequences for the set operations that use a map internally (Unique, Union, Intersect, SymmetricDifference, Minus, Without): none of them can match NaN against NaN, and none can deduplicate NaN values. The sort and positional operations are unaffected โ€” they do not use equality-based deduplication.

If you need NaN-aware set operations, pre-process your slice to replace NaNs with a canonical marker value.

Runtime panics from non-comparable interface values ยถ

Go's comparable constraint is checked at compile time, but interface types can carry dynamic values whose concrete type is not comparable (e.g., slices or maps stored in an any). Comparing such values causes a runtime panic. list does not recover from these panics โ€” it is the caller's responsibility to ensure interface slices contain only comparable dynamic values.

For documentation and examples, see https://github.com/bold-minds/list.

Index ยถ

Constants ยถ

This section is empty.

Variables ยถ

This section is empty.

Functions ยถ

func At ยถ added in v0.2.0

func At[T any](s []T, i int) (T, bool)

At returns the element at index i and whether the index was in range. Negative indexes count from the end: At(s, -1) returns the last element. Returns (zero, false) for an empty slice or out-of-range index.

func Between ยถ added in v0.2.0

func Between[T any](s []T, start, end int) []T

Between returns a new slice containing s[start:end], clamped to valid bounds. Negative start is clamped to 0; end greater than len(s) is clamped to len(s). If the resulting range is empty or inverted (start >= end after clamping), an empty slice is returned.

Unlike Go's native slice expression, Between never panics on out-of-range indexes.

func Compact ยถ added in v0.2.0

func Compact[T comparable](s []T) []T

Compact returns a new slice with every element equal to T's zero value removed. The zero value is whatever Go produces for `var v T`: `""` for strings, `0` for numerics, `false` for bool, nil for pointers/maps/slices/interfaces, and the all-zero struct for structs with comparable fields.

Compact requires T comparable so zero detection is expressed in pure Go (no reflection). Input is not mutated.

This is distinct from stdlib slices.Compact, which removes CONSECUTIVE duplicates. Use list.Unique for order-preserving full deduplication and list.Compact for zero-value stripping.

func DropL ยถ added in v0.2.1

func DropL[T any](s []T, n int) []T

DropL returns a new slice with the first n elements removed. It is the complement of FirstN: FirstN keeps the head, DropL discards it. If n <= 0, DropL returns a full copy of s. If n >= len(s), it returns an empty slice. Input is never mutated.

list.DropL([]int{1, 2, 3, 4, 5}, 2) // [3 4 5]
list.DropL([]int{1, 2, 3}, 10)      // []
list.DropL([]int{1, 2, 3}, 0)       // [1 2 3]

func DropR ยถ added in v0.2.1

func DropR[T any](s []T, n int) []T

DropR returns a new slice with the last n elements removed. It is the complement of LastN: LastN keeps the tail, DropR discards it. If n <= 0, DropR returns a full copy of s. If n >= len(s), it returns an empty slice. Input is never mutated.

list.DropR([]int{1, 2, 3, 4, 5}, 2) // [1 2 3]
list.DropR([]int{1, 2, 3}, 10)      // []
list.DropR([]int{1, 2, 3}, 0)       // [1 2 3]

func First ยถ added in v0.2.0

func First[T any](s []T) (T, bool)

First returns the first element of s and ok=true, or (zero, false) for an empty slice. Equivalent to At(s, 0).

func FirstN ยถ added in v0.2.0

func FirstN[T any](s []T, n int) []T

FirstN returns a new slice containing the first n elements of s. If n <= 0 returns an empty slice. If n >= len(s) returns a copy of s.

func Intersect ยถ

func Intersect[T comparable](slices ...[]T) []T

Intersect returns the unique elements present in every provided slice. Order is taken from the first slice. Variadic โ€” a single-slice call is equivalent to Unique; a zero-slice call returns an empty slice. A nil or empty slice anywhere in the input causes the result to be empty, since no element can appear in every slice.

func Last ยถ added in v0.2.0

func Last[T any](s []T) (T, bool)

Last returns the last element of s and ok=true, or (zero, false) for an empty slice. Equivalent to At(s, -1).

func LastN ยถ added in v0.2.0

func LastN[T any](s []T, n int) []T

LastN returns a new slice containing the last n elements of s. If n <= 0 returns an empty slice. If n >= len(s) returns a copy of s.

func Minus ยถ

func Minus[T comparable](a, b []T) []T

Minus returns the unique elements of a that are not present in b. Order is taken from a. Binary โ€” always exactly two arguments. To subtract multiple slices, compose with Union:

list.Minus(a, list.Union(b, c, d))

func Replace ยถ added in v0.2.0

func Replace[T comparable](s []T, old, newVal T) []T

Replace returns a new slice in which every element equal to old is replaced with newVal. Input is not mutated.

Use stdlib `s[i] = v` directly for single-index replacement โ€” list does not ship a positional Replace because Go already has it in the language.

func ReplaceFirst ยถ added in v0.2.0

func ReplaceFirst[T comparable](s []T, old, newVal T) []T

ReplaceFirst returns a new slice in which the first element equal to old is replaced with newVal. Subsequent occurrences are left unchanged. If old is not found, the returned slice is a copy of s with no changes. Input is not mutated.

func Reverse ยถ added in v0.2.0

func Reverse[T any](s []T) []T

Reverse returns a new slice containing the elements of s in reverse order. Input is not mutated.

func Sample ยถ added in v0.2.0

func Sample[T any](s []T) (T, bool)

Sample returns one uniformly-random element of s and ok=true, or (zero, false) for an empty slice. Uses math/rand/v2's top-level goroutine-safe source โ€” adequate for tests, fixtures, and UI randomization, but NOT for cryptographic purposes. Use crypto/rand directly if you need unpredictability guarantees.

func SampleN ยถ added in v0.2.0

func SampleN[T any](s []T, n int) []T

SampleN returns n distinct elements chosen uniformly at random from s, in random order. If n <= 0 returns empty; if n >= len(s) returns a Shuffle'd copy of s (implicitly capping n at len(s)).

The algorithm is a Fisherโ€“Yates partial shuffle: O(n) time, O(len(s)) space for the working copy.

func Shuffle ยถ added in v0.2.0

func Shuffle[T any](s []T) []T

Shuffle returns a new slice containing the elements of s in a uniformly-random order. Input is not mutated. Uses the same math/rand/v2 source as Sample โ€” adequate for tests and UI but not for cryptographic purposes.

func Sort ยถ added in v0.2.0

func Sort[T cmp.Ordered](s []T) []T

Sort returns a new slice containing the elements of s in ascending order. T must satisfy cmp.Ordered (strings, all integer widths, both float types, and named types with those underlying kinds). Input is not mutated.

NaN handling follows cmp.Compare: NaN sorts before every non-NaN value.

func SortBy ยถ added in v0.2.0

func SortBy[T any](s []T, less func(a, b T) int) []T

SortBy returns a new slice containing the elements of s sorted by the caller-supplied comparator. less must return negative / zero / positive for a<b / a==b / a>b, matching slices.SortFunc. Input is not mutated.

Use SortBy when T is not cmp.Ordered โ€” structs, interfaces, pointers, custom types with non-ordered underlying kinds โ€” or when the sort key is a derived field rather than the element itself.

func SortDesc ยถ added in v0.2.0

func SortDesc[T cmp.Ordered](s []T) []T

SortDesc returns a new slice containing the elements of s in descending order. T must satisfy cmp.Ordered. Input is not mutated.

NaN handling is the inverse of Sort: NaN sorts after every non-NaN value (because the comparator is reversed).

func SymmetricDifference ยถ added in v0.2.0

func SymmetricDifference[T comparable](a, b []T) []T

SymmetricDifference returns the unique elements present in a or b but not in both โ€” i.e., (a โˆช b) โˆ’ (a โˆฉ b). Order is taken from a first, then b. Binary โ€” always exactly two arguments.

func Union ยถ

func Union[T comparable](slices ...[]T) []T

Union returns the unique elements across all provided slices, preserving the order of first occurrence as each slice is walked in turn. Variadic โ€” accepts zero or more slices.

func Unique ยถ

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

Unique returns a new slice with duplicate elements removed, preserving the order of first occurrence. Returns an empty (non-nil) slice for nil or empty input.

func Without ยถ

func Without[T comparable](s []T, items ...T) []T

Without returns a new slice with all occurrences of the specified items removed, preserving the order of remaining elements.

Unlike Unique/Union/Intersect/Minus, Without does NOT deduplicate remaining elements. If s contains duplicates of values that are not in items, those duplicates remain in the output. For dedup + removal, chain: list.Unique(list.Without(s, v)).

Types ยถ

This section is empty.

Jump to

Keyboard shortcuts

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