slices

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Feb 20, 2022 License: MIT Imports: 0 Imported by: 0

Documentation

Overview

Package slices contains utilities for working with slices of arbitrary types.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func All

func All[T any](x []T, f func(T) bool) bool

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

func Any[T any](x []T, f func(T) bool) bool

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

func Chunk[T any](x []T, chunkSize int) [][]T

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

func CompactFunc[T any](x []T, eq func(T, T) bool) []T

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

func CompactInPlaceFunc[T any](x []T, eq func(T, T) bool) []T

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 CountFunc

func CountFunc[T any](a []T, f func(T) bool) int

Count returns the number of items in a for which f returns true.

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

func Filter[T any](x []T, keep func(t T) bool) []T

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

func FilterInPlace[T any](x []T, keep func(t T) bool) []T

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

func Grow[T any](x []T, n int) []T

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

func IndexFunc[T any](a []T, f func(T) bool) int

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

func Insert[T any](x []T, idx int, values ...T) []T

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

func LastIndexFunc[T any](a []T, f func(T) bool) int

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

func Map[T any, U any](x []T, f func(T) U) []U

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

func Partition[T any](x []T, f func(t T) bool)

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

func Reduce[T any, U any](x []T, initial U, f func(U, T) U) U

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

func Remove[T any](x []T, idx int, n int) []T

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

func RemoveUnordered[T any](x []T, idx int, n int) []T

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

func Repeat[T any](x T, n int) []T

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

func Runs[T any](x []T, same func(a, b T) bool) [][]T

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

func Shrink[T any](x []T, n int) []T

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.

Jump to

Keyboard shortcuts

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