Documentation
¶
Overview ¶
Package slices2 contains slice related helpers missing in standard "slices" package.
To avoid conflicts with standard "slices" package the package named as slices2:
import ( "github.com/Pilatuz/slices2" )
Some helpers able to do "in-place" work, i.e. there is no memory allocation for result. Such functions usually have "InPlace" suffix in their names.
Filtering and Rejecting ¶
Filter and Reject are very similar but use inversed condition.
Both have options to modify input slice "in-place" (without memory allocation).
Uniqueness ¶
Unique and UniqueBy remove duplicates from a slice. Unlike standard slices.Compact, they work with unsorted input. Also available "InPlace" versions for memory-efficient operations.
Set Operations ¶
The package provides functions for set operations:
- SetAnd — intersection (elements present in both slices)
- SetOr — union (unique elements from both slices)
- SetSub — difference (elements in s1 missing in s2)
- SetDiff — symmetric difference (elements present in only one of the slices)
All set operation functions have "By" variants for custom key extraction.
Sorting and Reversing ¶
SortInPlace and SortFuncInPlace sort a slice in ascending order. Sorted and SortedFunc return a new sorted slice. Reversed returns a new slice with elements in reverse order. ReverseInPlace reverses elements of a slice in place.
Transformation ¶
Transform transforms each element of a slice from one type to another. TransformEx transforms elements with error handling. Special error ErrSkip allows skipping elements. Deref dereferences pointers, skipping nil values.
Grouping ¶
GroupBy groups slice elements by a key.
Joining Slices ¶
Join joins multiple slices into one.
Cloning ¶
Clone makes a copy of a slice.
Set Type ¶
Type Set represents a set of unique elements based on map[K]struct{}. Methods:
- Push — add elements
- Pop — remove elements
- Has — check if element exists
- HasAll — check if all elements exist
- HasAny — check if any element exists
- All — get all elements as a slice
Go Versions ¶
The package supports Go 1.21+ and earlier versions. For Go 1.21+ it uses standard functions slices.Clone, slices.Reverse, slices.Sort.
Index ¶
- Variables
- func Clone[S ~[]E, E any](s S) S
- func Deref[T any](p *T) (T, error)
- func Filter[S ~[]E, E any](s S, condFn func(E) bool) S
- func FilterInPlace[S ~[]E, E any](s S, condFn func(E) bool) S
- func FromChannel[E any](ch <-chan E) []E
- func GroupBy[S ~[]E, E any, K comparable](s S, byFn func(E) K) map[K]S
- func Join[S ~[]E, E any](ss ...S) S
- func Reject[S ~[]E, E any](s S, condFn func(E) bool) S
- func RejectInPlace[S ~[]E, E any](s S, condFn func(E) bool) S
- func ReverseInPlace[S ~[]E, E any](s S)
- func Reversed[S ~[]E, E any](s S) S
- func SetAnd[S ~[]E, E comparable](s1 S, s2 S) S
- func SetAndBy[S ~[]E, E any, K comparable](s1 S, s2 S, byFn func(E) K) S
- func SetDiff[S ~[]E, E comparable](s1 S, s2 S) (out1 S, out2 S)
- func SetDiffBy[S ~[]E, E any, K comparable](s1 S, s2 S, byFn func(E) K) (out1 S, out2 S)
- func SetOr[S ~[]E, E comparable](s1 S, s2 S) S
- func SetOrBy[S ~[]E, E any, K comparable](s1 S, s2 S, byFn func(E) K) S
- func SetSub[S ~[]E, E comparable](s1 S, s2 S) S
- func SetSubBy[S ~[]E, E any, K comparable](s1 S, s2 S, byFn func(E) K) S
- func SortFuncInPlace[S ~[]E, E any](s S, cmp func(E, E) int)
- func SortInPlace[S ~[]E, E cmp.Ordered](s S)
- func Sorted[S ~[]E, E cmp.Ordered](s S) S
- func SortedFunc[S ~[]E, E any](s S, cmp func(E, E) int) S
- func ToChannel[S ~[]E, E any](s S, bufferSize int) <-chan E
- func Transform[E2 any, S1 ~[]E1, E1 any](s S1, convFn func(E1) E2) []E2
- func TransformEx[E2 any, S1 ~[]E1, E1 any](s S1, convFn func(E1) (E2, error)) ([]E2, error)
- func Unique[S ~[]E, E comparable](s S) S
- func UniqueBy[S ~[]E, K comparable, E any](s S, byFn func(E) K) S
- func UniqueInPlace[S ~[]E, E comparable](s S) S
- func UniqueInPlaceBy[S ~[]E, K comparable, E any](s S, byFn func(E) K) S
- type Set
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ErrSkip = errors.New("skip")
ErrSkip is a special sentinel error that indicates the current element should be skipped. Used in transformation functions with error handling.
Functions ¶
func Clone ¶
func Clone[S ~[]E, E any](s S) S
Clone makes a copy of a slice. Returns nil for nil slice.
func Deref ¶ added in v0.0.5
Deref dereferences pointers to values. Nil pointers are skipped with ErrSkip error.
func Filter ¶
Filter removes elements that DO NOT PASS condition. Returns new slice with elements that pass the condition.
The condFn function returns true for elements that should be kept.
Example ¶
ExampleFilter an example for `Filter` function.
package main
import (
"fmt"
"unicode/utf8"
"github.com/Pilatuz/slices2"
)
func main() {
ss := []string{"foo", "barbaz"}
cond := func(s string) bool {
return utf8.RuneCountInString(s) > 3
}
fmt.Println(slices2.Filter(ss, cond))
}
Output: [barbaz]
func FilterInPlace ¶
FilterInPlace removes elements that DO NOT PASS condition. Returns original slice with elements removed in-place (no memory allocation).
The condFn function returns true for elements that should be kept.
func FromChannel ¶
func FromChannel[E any](ch <-chan E) []E
FromChannel drains the channel ch into a slice.
It collects ALL the values from channel ch until the channel is closed.
Example ¶
ExampleFromChannel an example for `FromChannel` function.
package main
import (
"fmt"
"sync"
"github.com/Pilatuz/slices2"
)
func main() {
wg := &sync.WaitGroup{}
errCh := make(chan error)
wg.Add(3)
go func() {
defer wg.Done()
errCh <- nil
}()
go func() {
defer wg.Done()
errCh <- nil
}()
go func() {
defer wg.Done()
errCh <- nil
}()
go func() {
wg.Wait()
close(errCh)
}()
res := slices2.FromChannel(errCh)
fmt.Println(res)
}
Output: [<nil> <nil> <nil>]
func GroupBy ¶ added in v0.0.3
func GroupBy[S ~[]E, E any, K comparable](s S, byFn func(E) K) map[K]S
GroupBy groups slice elements by a key. Returns a map where keys are results of byFn function and values are slices of elements with that key.
Example ¶
ExampleGroupBy an example for `GroupBy` function.
package main
import (
"fmt"
"github.com/Pilatuz/slices2"
)
func main() {
words := []string{"apple", "apricot", "banana", "blueberry"}
grouped := slices2.GroupBy(words, func(s string) string { return s[:1] })
fmt.Println(grouped["a"])
fmt.Println(grouped["b"])
}
Output: [apple apricot] [banana blueberry]
func Join ¶
func Join[S ~[]E, E any](ss ...S) S
Join joins multiple slices into one. Returns a new slice containing elements from all input slices.
Example ¶
ExampleJoin an example for `Join` function.
package main
import (
"fmt"
"github.com/Pilatuz/slices2"
)
func main() {
s := slices2.Join(
[]string{"foo", "bar"},
[]string{"baz"})
fmt.Println(s)
}
Output: [foo bar baz]
func Reject ¶
Reject removes elements that DO PASS condition. Returns new slice with elements that do NOT pass the condition.
The condFn function returns true for elements that should be removed.
Example ¶
ExampleReject an example for `Reject` function.
package main
import (
"fmt"
"unicode/utf8"
"github.com/Pilatuz/slices2"
)
func main() {
ss := []string{"foo", "barbaz"}
cond := func(s string) bool {
return utf8.RuneCountInString(s) > 3
}
fmt.Println(slices2.Reject(ss, cond))
}
Output: [foo]
func RejectInPlace ¶
RejectInPlace removes elements that DO PASS condition. Returns original slice with elements removed in-place (no memory allocation).
The condFn function returns true for elements that should be removed.
func ReverseInPlace ¶ added in v0.0.3
func ReverseInPlace[S ~[]E, E any](s S)
ReverseInPlace reverses elements of a slice (in place).
func Reversed ¶ added in v0.0.3
func Reversed[S ~[]E, E any](s S) S
Reversed returns a new slice with elements in reverse order. As opposite to ReverseInPlace, this function always allocates a new array.
Example ¶
ExampleReversed an example for `Reversed` function.
package main
import (
"fmt"
"github.com/Pilatuz/slices2"
)
func main() {
s := []int{1, 2, 3}
r := slices2.Reversed(s)
fmt.Println(s)
fmt.Println(r)
}
Output: [1 2 3] [3 2 1]
func SetAnd ¶
func SetAnd[S ~[]E, E comparable](s1 S, s2 S) S
SetAnd returns the intersection between two sets. I.e. elements presented in both slices. Order is preserved from s2.
Example ¶
ExampleSetAnd an example for `SetAnd` function.
package main
import (
"fmt"
"github.com/Pilatuz/slices2"
)
func main() {
a := []string{"foo", "bar"}
b := []string{"bar", "baz"}
c := slices2.SetAnd(a, b)
fmt.Println(a, "&", b, "=", c)
}
Output: [foo bar] & [bar baz] = [bar]
func SetAndBy ¶
func SetAndBy[S ~[]E, E any, K comparable](s1 S, s2 S, byFn func(E) K) S
SetAndBy returns the intersection between two sets by custom key. I.e. elements presented in both slices. The byFn function extracts a comparison key from each element. Order is preserved from s2.
func SetDiff ¶
func SetDiff[S ~[]E, E comparable](s1 S, s2 S) (out1 S, out2 S)
SetDiff returns the difference between two sets. Returns two slices:
- out1: elements presented in s1 but missing in s2
- out2: elements presented in s2 but missing in s1
Example ¶
ExampleSetDiff an example for `SetDiff` function.
package main
import (
"fmt"
"github.com/Pilatuz/slices2"
)
func main() {
a := []string{"foo", "bar"}
b := []string{"bar", "baz"}
removed, added := slices2.SetDiff(a, b)
fmt.Println(a, "diff", b)
fmt.Println("added:", added)
fmt.Println("removed:", removed)
}
Output: [foo bar] diff [bar baz] added: [baz] removed: [foo]
func SetDiffBy ¶
func SetDiffBy[S ~[]E, E any, K comparable](s1 S, s2 S, byFn func(E) K) (out1 S, out2 S)
SetDiffBy returns the difference between two slices by custom key. Returns two slices:
- out1: elements presented in s1 but missing in s2
- out2: elements presented in s2 but missing in s1
The byFn function extracts a comparison key from each element.
func SetOr ¶
func SetOr[S ~[]E, E comparable](s1 S, s2 S) S
SetOr returns the union between two sets. I.e. unique elements presented in at least one slice. Order: first elements from s1, then new elements from s2.
Example ¶
ExampleSetOr an example for `SetOr` function.
package main
import (
"fmt"
"github.com/Pilatuz/slices2"
)
func main() {
a := []string{"foo", "bar"}
b := []string{"bar", "baz"}
c := slices2.SetOr(a, b)
fmt.Println(a, "|", b, "=", c)
}
Output: [foo bar] | [bar baz] = [foo bar baz]
func SetOrBy ¶
func SetOrBy[S ~[]E, E any, K comparable](s1 S, s2 S, byFn func(E) K) S
SetOrBy returns the union between two sets by custom key. I.e. unique elements presented in at least one slice. The byFn function extracts a comparison key from each element. Order: first elements from s1, then new elements from s2.
func SetSub ¶
func SetSub[S ~[]E, E comparable](s1 S, s2 S) S
SetSub returns set where all s2 elements removed from s1. I.e. all elements presented in s1 and missing in s2.
Example ¶
ExampleSetSub an example for `SetSub` function.
package main
import (
"fmt"
"github.com/Pilatuz/slices2"
)
func main() {
a := []string{"foo", "bar"}
b := []string{"bar", "baz"}
c := slices2.SetSub(a, b)
fmt.Println(a, "-", b, "=", c)
}
Output: [foo bar] - [bar baz] = [foo]
func SetSubBy ¶
func SetSubBy[S ~[]E, E any, K comparable](s1 S, s2 S, byFn func(E) K) S
SetSubBy returns set where all s2 elements removed from s1 by custom key. I.e. all elements presented in s1 and missing in s2.
The byFn function extracts a comparison key from each element.
func SortFuncInPlace ¶ added in v0.0.3
SortFuncInPlace sorts an input slice s of any type in ascending order using the cmp function. The cmp function should return:
- negative value if a < b
- zero if a == b
- positive value if a > b
This sort is not guaranteed to be stable.
func SortInPlace ¶ added in v0.0.3
SortInPlace sorts an input slice s of any ordered type in ascending order (in place). This sort is not guaranteed to be stable.
func Sorted ¶ added in v0.0.3
Sorted returns a new slice with elements of input slice s sorted in ascending order. As opposite to SortInPlace, this function always allocates a new array.
Example ¶
ExampleSorted an example for `Sorted` function.
package main
import (
"fmt"
"github.com/Pilatuz/slices2"
)
func main() {
s := []int{3, 1, 2}
r := slices2.Sorted(s)
fmt.Println(s)
fmt.Println(r)
}
Output: [3 1 2] [1 2 3]
func SortedFunc ¶ added in v0.0.3
SortedFunc returns a new slice with elements of input slice s sorted using the cmp function. As opposite to SortFuncInPlace, this function always allocates a new array.
func ToChannel ¶
ToChannel converts a slice to read-only channel.
All values from slice s will be sent to new channel.
func Transform ¶
Transform transforms each slice element from type E1 to type E2. Returns a new slice of transformed elements.
Example ¶
ExampleTransform an example for `Transform` function.
package main
import (
"fmt"
"strconv"
"github.com/Pilatuz/slices2"
)
func main() {
fromStr := func(s string) int {
out, _ := strconv.Atoi(s)
return out
}
ss := []string{"123", "456"}
ii := slices2.Transform(ss, fromStr)
fmt.Println(ii)
}
Output: [123 456]
func TransformEx ¶ added in v0.0.5
TransformEx transforms each slice element from type E1 to type E2 with error handling. Stops on the first error. Special error ErrSkip skips elements.
func Unique ¶
func Unique[S ~[]E, E comparable](s S) S
Unique removes duplicates from a slice. Returns new slice with unique elements. Order is preserved (first occurrence remains).
Example ¶
ExampleUnique an example for `Unique` function.
package main
import (
"fmt"
"github.com/Pilatuz/slices2"
)
func main() {
s := []int{4, 1, 2, 1, 2, 3, 2, 1}
fmt.Println(slices2.Unique(s))
}
Output: [4 1 2 3]
func UniqueBy ¶
func UniqueBy[S ~[]E, K comparable, E any](s S, byFn func(E) K) S
UniqueBy removes duplicates from a slice by custom key. Returns new slice with unique elements. The byFn function extracts a comparison key from each element. Order is preserved (first occurrence remains).
func UniqueInPlace ¶
func UniqueInPlace[S ~[]E, E comparable](s S) S
UniqueInPlace removes duplicates from a slice. Returns original slice with duplicates removed in-place (no memory allocation). Order is preserved (first occurrence remains).
func UniqueInPlaceBy ¶
func UniqueInPlaceBy[S ~[]E, K comparable, E any](s S, byFn func(E) K) S
UniqueInPlaceBy removes duplicates from a slice by custom key. Returns original slice with duplicates removed in-place (no memory allocation). The byFn function extracts a comparison key from each element. Order is preserved (first occurrence remains).
Types ¶
type Set ¶ added in v0.0.6
type Set[K comparable] map[K]struct{}
Set represents a collection of unique elements. It's a thin wrapper over map[K]struct{} for convenient set operations.
The Set type supports all basic set operations: add (Push), remove (Pop), check presence (Has, HasAll, HasAny), and get all elements (All).
Example ¶
ExampleSet an example for Set type and its methods.
package main
import (
"fmt"
"sort"
"github.com/Pilatuz/slices2"
)
func main() {
// Create a new set
s := slices2.NewSet("foo", "bar", "baz")
fmt.Println("Set:", s)
// Check if element exists
fmt.Println("Has(foo):", s.Has("foo"))
fmt.Println("Has(qux):", s.Has("qux"))
// Add elements
s.Push("qux")
fmt.Println("After Push(qux):", s)
// Remove elements
s.Pop("bar")
fmt.Println("After Pop(bar):", s)
// Check all elements (order is not guaranteed, so sort for predictable output)
all := s.All()
sort.Strings(all)
fmt.Println("All():", all) // slices2.Sorted(s.All())
// Check HasAll
fmt.Println("HasAll(foo, qux):", s.HasAll("foo", "qux"))
fmt.Println("HasAll(foo, bar):", s.HasAll("foo", "bar"))
// Check HasAny
fmt.Println("HasAny(foo, bar):", s.HasAny("foo", "bar"))
fmt.Println("HasAny(qux, quux):", s.HasAny("qux", "quux"))
}
Output: Set: map[bar:{} baz:{} foo:{}] Has(foo): true Has(qux): false After Push(qux): map[bar:{} baz:{} foo:{} qux:{}] After Pop(bar): map[baz:{} foo:{} qux:{}] All(): [baz foo qux] HasAll(foo, qux): true HasAll(foo, bar): false HasAny(foo, bar): true HasAny(qux, quux): true
func NewSet ¶ added in v0.0.6
func NewSet[K comparable](kk ...K) Set[K]
NewSet creates a new set with optional elements. Duplicates are automatically removed.
func NewSetBy ¶ added in v0.0.6
func NewSetBy[S ~[]E, E any, K comparable](s S, byFn func(E) K) Set[K]
NewSetBy creates a new set from a slice with element transformation via key. The byFn function extracts a key from each element.
Example ¶
ExampleNewSetBy an example for NewSetBy function.
package main
import (
"fmt"
"github.com/Pilatuz/slices2"
)
func main() {
type Person struct {
Name string
Age int
}
people := []Person{{"Alice", 30}, {"Bob", 25}, {"Charlie", 30}}
// Group by age
ages := slices2.NewSetBy(people, func(p Person) int { return p.Age })
fmt.Println(ages)
}
Output: map[25:{} 30:{}]
func (Set[K]) All ¶ added in v0.0.6
func (s Set[K]) All() []K
All returns all elements of the set as a slice. Element order is undefined (depends on map implementation). Returns nil for empty sets.
func (Set[K]) Has ¶ added in v0.0.6
Has checks if an element is present in the set. Returns true if the element exists.
func (Set[K]) HasAll ¶ added in v0.0.6
HasAll checks if ALL specified elements are present in the set. Returns true if all elements exist. Empty argument list returns true.
func (Set[K]) HasAny ¶ added in v0.0.6
HasAny checks if ANY of the specified elements is present in the set. Returns true if at least one element exists in the set. Empty argument list returns false.