Documentation
¶
Overview ¶
Package slices contains utilities for working with slices of arbitrary types.
Index ¶
- func All[T any](x []T, f func(T) bool) bool
- func Any[T any](x []T, f func(T) bool) bool
- func Chunk[T any](x []T, chunkSize int) [][]T
- func Clear[T any](x []T)
- func Clone[T any](x []T) []T
- func Compact[T comparable](x []T) []T
- func CompactFunc[T any](x []T, eq func(T, T) bool) []T
- func CompactInPlace[T comparable](x []T) []T
- func CompactInPlaceFunc[T any](x []T, eq func(T, T) bool) []T
- func Count[T comparable](a []T, item T) int
- func CountFunc[T any](a []T, f func(T) bool) int
- func Equal[T comparable](a, b []T) bool
- func Fill[T any](a []T, x T)
- func Filter[T any](x []T, keep func(t T) bool) []T
- func FilterInPlace[T any](x []T, keep func(t T) bool) []T
- func Grow[T any](x []T, n int) []T
- func Index[T comparable](a []T, item T) int
- func IndexFunc[T any](a []T, f func(T) bool) int
- func Insert[T any](x []T, idx int, values ...T) []T
- func Join[T any](in ...[]T) []T
- func LastIndex[T comparable](a []T, item T) int
- func LastIndexFunc[T any](a []T, f func(T) bool) int
- func Map[T any, U any](x []T, f func(T) U) []U
- func Partition[T any](x []T, f func(t T) bool)
- func Reduce[T any, U any](x []T, initial U, f func(U, T) U) U
- func Remove[T any](x []T, idx int, n int) []T
- func RemoveUnordered[T any](x []T, idx int, n int) []T
- func Repeat[T any](x T, n int) []T
- func Reverse[T any](x []T)
- func Runs[T any](x []T, same func(a, b T) bool) [][]T
- func Shrink[T any](x []T, n int) []T
- func Unique[T comparable](x []T) []T
- func UniqueInPlace[T comparable](x []T) []T
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func All ¶
All returns true if f(x[i]) returns true for all i. Trivially, returns true if x is empty.
Example ¶
package main
import (
"fmt"
"github.com/bradenaw/juniper/slices"
)
func main() {
isOdd := func(x int) bool {
return x%2 != 0
}
allOdd := slices.All([]int{1, 3, 5}, isOdd)
fmt.Println(allOdd)
allOdd = slices.All([]int{1, 3, 6}, isOdd)
fmt.Println(allOdd)
}
Output: true false
func Any ¶
Any returns true if f(x[i]) returns true for any i. Trivially, returns false if x is empty.
Example ¶
package main
import (
"fmt"
"github.com/bradenaw/juniper/slices"
)
func main() {
isOdd := func(x int) bool {
return x%2 != 0
}
anyOdd := slices.Any([]int{2, 3, 4}, isOdd)
fmt.Println(anyOdd)
anyOdd = slices.Any([]int{2, 4, 6}, isOdd)
fmt.Println(anyOdd)
}
Output: true false
func Chunk ¶
Chunk returns non-overlapping chunks of x. The last chunk will be smaller than chunkSize if len(x) is not a multiple of chunkSize.
Returns an empty slice if len(x)==0. Panics if chunkSize <= 0.
Example ¶
package main
import (
"fmt"
"github.com/bradenaw/juniper/slices"
)
func main() {
a := []string{"a", "b", "c", "d", "e", "f", "g", "h"}
chunks := slices.Chunk(a, 3)
fmt.Println(chunks)
}
Output: [[a b c] [d e f] [g h]]
func Clear ¶
func Clear[T any](x []T)
Clear fills x with the zero value of T.
Example ¶
package main
import (
"fmt"
"github.com/bradenaw/juniper/slices"
)
func main() {
x := []int{1, 2, 3}
slices.Clear(x)
fmt.Println(x)
}
Output: [0 0 0]
func Clone ¶
func Clone[T any](x []T) []T
Clone creates a new slice and copies the elements of x into it.
Example ¶
package main
import (
"fmt"
"github.com/bradenaw/juniper/slices"
)
func main() {
x := []int{1, 2, 3}
cloned := slices.Clone(x)
fmt.Println(cloned)
}
Output: [1 2 3]
func Compact ¶
func Compact[T comparable](x []T) []T
Compact returns a slice containing only the first item from each contiguous run of the same item.
For example, this can be used to remove duplicates more cheaply than Unique when the slice is already in sorted order.
Example ¶
package main
import (
"fmt"
"github.com/bradenaw/juniper/slices"
)
func main() {
x := []string{"a", "a", "b", "c", "c", "c", "a"}
compacted := slices.Compact(x)
fmt.Println(compacted)
}
Output: [a b c a]
func CompactFunc ¶
CompactFunc returns a slice containing only the first item from each contiguous run of items for which eq returns true.
Example ¶
package main
import (
"fmt"
"github.com/bradenaw/juniper/slices"
)
func main() {
x := []string{
"bank",
"beach",
"ghost",
"goat",
"group",
"yaw",
"yew",
}
compacted := slices.CompactFunc(x, func(a, b string) bool {
return a[0] == b[0]
})
fmt.Println(compacted)
}
Output: [bank ghost yaw]
func CompactInPlace ¶
func CompactInPlace[T comparable](x []T) []T
CompactInPlace returns a slice containing only the first item from each contiguous run of the same item. This is done in-place and so modifies the contents of x. The modified slice is returned.
For example, this can be used to remove duplicates more cheaply than Unique when the slice is already in sorted order.
Example ¶
package main
import (
"fmt"
"github.com/bradenaw/juniper/slices"
)
func main() {
x := []string{"a", "a", "b", "c", "c", "c", "a"}
compacted := slices.CompactInPlace(x)
fmt.Println(compacted)
}
Output: [a b c a]
func CompactInPlaceFunc ¶
CompactInPlaceFunc returns a slice containing only the first item from each contiguous run of items for which eq returns true. This is done in-place and so modifies the contents of x. The modified slice is returned.
Example ¶
package main
import (
"fmt"
"github.com/bradenaw/juniper/slices"
)
func main() {
x := []string{
"bank",
"beach",
"ghost",
"goat",
"group",
"yaw",
"yew",
}
compacted := slices.CompactInPlaceFunc(x, func(a, b string) bool {
return a[0] == b[0]
})
fmt.Println(compacted)
}
Output: [bank ghost yaw]
func Count ¶
func Count[T comparable](a []T, item T) int
Count returns the number of times item appears in a.
Example ¶
package main
import (
"fmt"
"github.com/bradenaw/juniper/slices"
)
func main() {
x := []string{"a", "b", "a", "a", "b"}
fmt.Println(slices.Count(x, "a"))
}
Output: 3
func Equal ¶
func Equal[T comparable](a, b []T) bool
Equal returns true if a and b contain the same items in the same order.
Example ¶
package main
import (
"fmt"
"github.com/bradenaw/juniper/slices"
)
func main() {
x := []string{"a", "b", "c"}
y := []string{"a", "b", "c"}
z := []string{"a", "b", "d"}
fmt.Println(slices.Equal(x, y))
fmt.Println(slices.Equal(x[:2], y))
fmt.Println(slices.Equal(z, y))
}
Output: true false false
func Fill ¶
func Fill[T any](a []T, x T)
Fill fills a with copies of x.
Example ¶
package main
import (
"fmt"
"github.com/bradenaw/juniper/slices"
)
func main() {
x := []int{1, 2, 3}
slices.Fill(x, 5)
fmt.Println(x)
}
Output: [5 5 5]
func Filter ¶
Filter returns a slice containing only the elements of x for which keep() returns true in the same order that they appeared in x.
Example ¶
package main
import (
"fmt"
"github.com/bradenaw/juniper/slices"
)
func main() {
x := []int{5, -9, -2, 1, -4, 8, 3}
x = slices.Filter(x, func(value int) bool {
return value > 0
})
fmt.Println(x)
}
Output: [5 1 8 3]
func FilterInPlace ¶
FilterInPlace returns a slice containing only the elements of x for which keep() returns true in the same order that they appeared in x. This is done in-place and so modifies the contents of x. The modified slice is returned.
Example ¶
package main
import (
"fmt"
"github.com/bradenaw/juniper/slices"
)
func main() {
x := []int{5, -9, -2, 1, -4, 8, 3}
x = slices.FilterInPlace(x, func(value int) bool {
return value > 0
})
fmt.Println(x)
}
Output: [5 1 8 3]
func Grow ¶
Grow grows x's capacity by reallocating, if necessary, to fit n more elements and returns the modified slice. This does not change the length of x. After Grow(x, n), the following n append()s to x will not need to reallocate.
Example ¶
package main
import (
"fmt"
"github.com/bradenaw/juniper/slices"
)
func main() {
x := make([]int, 0, 1)
x = slices.Grow(x, 4)
fmt.Println(len(x))
fmt.Println(cap(x))
x = append(x, 1)
addr := &x[0]
x = append(x, 2)
fmt.Println(addr == &x[0])
x = append(x, 3)
fmt.Println(addr == &x[0])
x = append(x, 4)
fmt.Println(addr == &x[0])
}
Output: 0 4 true true true
func Index ¶
func Index[T comparable](a []T, item T) int
Index returns the first index of item in a, or -1 if item is not in a.
Example ¶
package main
import (
"fmt"
"github.com/bradenaw/juniper/slices"
)
func main() {
x := []string{"a", "b", "a", "a", "b"}
fmt.Println(slices.Index(x, "b"))
fmt.Println(slices.Index(x, "c"))
}
Output: 1 -1
func IndexFunc ¶
Index returns the first index in a for which f(a[i]) returns true, or -1 if there are no such items.
Example ¶
package main
import (
"fmt"
"strings"
"github.com/bradenaw/juniper/slices"
)
func main() {
x := []string{
"blue",
"green",
"yellow",
"gold",
"red",
}
fmt.Println(slices.IndexFunc(x, func(s string) bool {
return strings.HasPrefix(s, "g")
}))
fmt.Println(slices.IndexFunc(x, func(s string) bool {
return strings.HasPrefix(s, "p")
}))
}
Output: 1 -1
func Insert ¶
Insert inserts the given values starting at index idx, shifting elements after idx to the right and growing the slice to make room. Insert will expand the length of the slice up to its capacity if it can, if this isn't desired then x should be resliced to have capacity equal to its length:
x[:len(x):len(x)]
The time cost is O(n+m) where n is len(values) and m is len(x[idx:]).
Example ¶
package main
import (
"fmt"
"github.com/bradenaw/juniper/slices"
)
func main() {
x := []string{"a", "b", "c", "d", "e"}
x = slices.Insert(x, 3, "f", "g")
fmt.Println(x)
}
Output: [a b c f g d e]
func Join ¶
func Join[T any](in ...[]T) []T
Join joins together the contents of each in.
Example ¶
package main
import (
"fmt"
"github.com/bradenaw/juniper/slices"
)
func main() {
joined := slices.Join(
[]string{"a", "b", "c"},
[]string{"x", "y"},
[]string{"l", "m", "n", "o"},
)
fmt.Println(joined)
}
Output: [a b c x y l m n o]
func LastIndex ¶
func LastIndex[T comparable](a []T, item T) int
LastIndex returns the last index of item in a, or -1 if item is not in a.
Example ¶
package main
import (
"fmt"
"github.com/bradenaw/juniper/slices"
)
func main() {
x := []string{"a", "b", "a", "a", "b"}
fmt.Println(slices.LastIndex(x, "a"))
fmt.Println(slices.LastIndex(x, "c"))
}
Output: 3 -1
func LastIndexFunc ¶
LastIndexFunc returns the last index in a for which f(a[i]) returns true, or -1 if there are no such items.
Example ¶
package main
import (
"fmt"
"strings"
"github.com/bradenaw/juniper/slices"
)
func main() {
x := []string{
"blue",
"green",
"yellow",
"gold",
"red",
}
fmt.Println(slices.LastIndexFunc(x, func(s string) bool {
return strings.HasPrefix(s, "g")
}))
fmt.Println(slices.LastIndexFunc(x, func(s string) bool {
return strings.HasPrefix(s, "p")
}))
}
Output: 3 -1
func Map ¶
Map creates a new slice by applying f to each element of x.
Example ¶
package main
import (
"fmt"
"github.com/bradenaw/juniper/slices"
)
func main() {
toHalfFloat := func(x int) float32 {
return float32(x) / 2
}
a := []int{1, 2, 3}
floats := slices.Map(a, toHalfFloat)
fmt.Println(floats)
}
Output: [0.5 1 1.5]
func Partition ¶
Partition moves elements of x such that all elements for which f returns false are at the beginning and all elements for which f returns true are at the end. It makes no other guarantees about the final order of elements.
Example ¶
package main
import (
"fmt"
"github.com/bradenaw/juniper/slices"
)
func main() {
a := []int{11, 3, 4, 2, 7, 8, 0, 1, 14}
slices.Partition(a, func(x int) bool { return x%2 == 0 })
fmt.Println(a)
}
Output: [11 3 1 7 2 8 0 4 14]
func Reduce ¶
Reduce reduces x to a single value using the reduction function f.
Example ¶
package main
import (
"fmt"
"math"
"github.com/bradenaw/juniper/slices"
"github.com/bradenaw/juniper/xmath"
)
func main() {
x := []int{3, 1, 2}
sum := slices.Reduce(x, 0, func(x, y int) int { return x + y })
fmt.Println(sum)
min := slices.Reduce(x, math.MaxInt, xmath.Min[int])
fmt.Println(min)
}
Output: 6 1
func Remove ¶
Remove removes n elements from x starting at index idx and returns the modified slice. This requires shifting the elements after the removed elements over, and so its cost is linear in the number of elements shifted.
Example ¶
package main
import (
"fmt"
"github.com/bradenaw/juniper/slices"
)
func main() {
x := []int{1, 2, 3, 4, 5}
x = slices.Remove(x, 1, 2)
fmt.Println(x)
}
Output: [1 4 5]
func RemoveUnordered ¶
RemoveUnordered removes n elements from x starting at index idx and returns the modified slice. This is done by moving up to n elements from the end of the slice into the gap left by removal, which is linear in n (rather than len(x)-idx as Remove() is), but does not preserve order of the remaining elements.
Example ¶
package main
import (
"fmt"
"github.com/bradenaw/juniper/slices"
)
func main() {
x := []int{1, 2, 3, 4, 5}
x = slices.RemoveUnordered(x, 1, 1)
fmt.Println(x)
x = slices.RemoveUnordered(x, 1, 2)
fmt.Println(x)
}
Output: [1 5 3 4] [1 4]
func Repeat ¶
Repeat returns a slice with length n where every item is x.
Example ¶
package main
import (
"fmt"
"github.com/bradenaw/juniper/slices"
)
func main() {
x := slices.Repeat("a", 4)
fmt.Println(x)
}
Output: [a a a a]
func Reverse ¶
func Reverse[T any](x []T)
Reverse reverses the elements of x in place.
Example ¶
package main
import (
"fmt"
"github.com/bradenaw/juniper/slices"
)
func main() {
x := []string{"a", "b", "c", "d", "e"}
slices.Reverse(x)
fmt.Println(x)
}
Output: [e d c b a]
func Runs ¶
Runs returns a slice of slices. The inner slices are contiguous runs of elements from x such that same(a, b) returns true for any a and b in the run.
same(a, a) must return true. If same(a, b) and same(b, c) both return true, then same(a, c) must also.
The returned slices use the same underlying array as x.
Example ¶
package main
import (
"fmt"
"github.com/bradenaw/juniper/slices"
)
func main() {
x := []int{2, 4, 0, 7, 1, 3, 9, 2, 8}
parityRuns := slices.Runs(x, func(a, b int) bool {
return a%2 == b%2
})
fmt.Println(parityRuns)
}
Output: [[2 4 0] [7 1 3 9] [2 8]]
func Shrink ¶
Shrink shrinks x's capacity by reallocating, if necessary, so that cap(x) <= len(x) + n.
Example ¶
package main
import (
"fmt"
"github.com/bradenaw/juniper/slices"
)
func main() {
x := make([]int, 3, 15)
x[0] = 0
x[1] = 1
x[2] = 2
fmt.Println(x)
fmt.Println(cap(x))
x = slices.Shrink(x, 0)
fmt.Println(x)
fmt.Println(cap(x))
}
Output: [0 1 2] 15 [0 1 2] 3
func Unique ¶
func Unique[T comparable](x []T) []T
Unique returns a slice that contains only the first instance of each unique item in x, preserving order.
Compact is more efficient if duplicates are already adjacent in x, for example if x is in sorted order.
Example ¶
package main
import (
"fmt"
"github.com/bradenaw/juniper/slices"
)
func main() {
a := []string{"a", "b", "b", "c", "a", "b", "b", "c"}
unique := slices.Unique(a)
fmt.Println(unique)
}
Output: [a b c]
func UniqueInPlace ¶
func UniqueInPlace[T comparable](x []T) []T
UniqueInPlace returns a slice that contains only the first instance of each unique item in x, preserving order. This is done in-place and so modifies the contents of x. The modified slice is returned.
Compact is more efficient if duplicates are already adjacent in x, for example if x is in sorted order.
Example ¶
package main
import (
"fmt"
"github.com/bradenaw/juniper/slices"
)
func main() {
a := []string{"a", "b", "b", "c", "a", "b", "b", "c"}
unique := slices.UniqueInPlace(a)
fmt.Println(unique)
}
Output: [a b c]
Types ¶
This section is empty.