gslice

package
v1.1.0 Latest Latest
Warning

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

Go to latest
Published: Jul 4, 2025 License: Apache-2.0 Imports: 10 Imported by: 26

Documentation ΒΆ

Overview ΒΆ

Package gslice provides generic operations for slices.

πŸ’‘ HINT: We provide similar functionality for different types in different packages. For example, Clone for copying slice while github.com/bytedance/gg/gmap.Clone for copying map.

Operations ΒΆ

High-order functions:

CRUD operations:

Partition operations:

Math operations:

Convert to Map:

Set operations:

Re-order operations:

Type casting/assertion/conversion:

Predicates:

Negative index ΒΆ

Some of operations (such as Get, Insert and Slice) support negative index like Python. The diagram is helpful too for remembering how negative index work:

         β”Œβ”€β”€β”€β”¬β”€β”€β”€β”¬β”€β”€β”€β”¬β”€β”€β”€β”¬β”€β”€β”€β”¬β”€β”€β”€β”
         β”‚ g β”‚ o β”‚ l β”‚ a β”‚ n β”‚ g β”‚
         β””β”€β”€β”€β”΄β”€β”€β”€β”΄β”€β”€β”€β”΄β”€β”€β”€β”΄β”€β”€β”€β”΄β”€β”€β”€β”˜
positive:  0   1   2   3   4   5  (0-based index from start)
negative: -6  -5  -4  -3  -2  -1  (negative index from end)
Example ΒΆ
// High-order function
fmt.Println(Map([]int{1, 2, 3, 4, 5}, strconv.Itoa)) // ["1", "2", "3", "4", "5"]
isEven := func(i int) bool { return i%2 == 0 }
fmt.Println(Filter([]int{1, 2, 3, 4, 5}, isEven))                  // [2, 4]
fmt.Println(Reduce([]int{1, 2, 3, 4, 5}, gvalue.Add[int]).Value()) // 15
fmt.Println(Any([]int{1, 2, 3, 4, 5}, isEven))                     // true
fmt.Println(All([]int{1, 2, 3, 4, 5}, isEven))                     // false

// CRUD operation
fmt.Println(Contains([]int{1, 2, 3, 4, 5}, 2))          // true
fmt.Println(ContainsAny([]int{1, 2, 3, 4, 5}, 2, 6))    // true
fmt.Println(ContainsAll([]int{1, 2, 3, 4, 5}, 2, 6))    // false
fmt.Println(Index([]int{1, 2, 3, 4, 5}, 3).Value())     // 2
fmt.Println(Find([]int{1, 2, 3, 4, 5}, isEven).Value()) // 2
fmt.Println(First([]int{1, 2, 3, 4, 5}).Value())        // 1
fmt.Println(Get([]int{1, 2, 3, 4, 5}, 1).Value())       // 2
fmt.Println(Get([]int{1, 2, 3, 4, 5}, -1).Value())      //  5

// Partion operation
fmt.Println(Range(1, 5))                             // [1, 2, 3, 4]
fmt.Println(RangeWithStep(5, 1, -2))                 // [5, 3]
fmt.Println(Take([]int{1, 2, 3, 4, 5}, 2))           // [1, 2]
fmt.Println(Take([]int{1, 2, 3, 4, 5}, -2))          // [4, 5]
fmt.Println(Slice([]int{1, 2, 3, 4, 5}, 1, 3))       // [2, 3]
fmt.Println(Chunk([]int{1, 2, 3, 4, 5}, 2))          // [[1, 2] [3, 4] [5]]
fmt.Println(Divide([]int{1, 2, 3, 4, 5}, 2))         // [[1, 2, 3] [4, 5]]
fmt.Println(Concat([]int{1, 2}, []int{3, 4, 5}))     // [1, 2, 3, 4, 5]
fmt.Println(Flatten([][]int{{1, 2}, {3, 4, 5}}))     // [1, 2, 3, 4, 5]
fmt.Println(Partition([]int{1, 2, 3, 4, 5}, isEven)) // [2, 4], [1, 3, 5]

// Math operation
fmt.Println(Max([]int{1, 2, 3, 4, 5}).Value())             // 5
fmt.Println(Min([]int{1, 2, 3, 4, 5}).Value())             // 1
fmt.Println(MinMax([]int{1, 2, 3, 4, 5}).Value().Values()) // 1 5
fmt.Println(Sum([]int{1, 2, 3, 4, 5}))                     // 15

// Convert to Map
fmt.Println(gson.ToString(ToMap([]int{1, 2, 3, 4, 5}, func(i int) (string, int) { return strconv.Itoa(i), i }))) // {"1":1,"2":2,"3":3,"4":4,"5":5}
fmt.Println(gson.ToString(ToMapValues([]int{1, 2, 3, 4, 5}, strconv.Itoa)))                                      // {"1":1,"2":2,"3":3,"4":4,"5":5}
fmt.Println(gson.ToString(GroupBy([]int{1, 2, 3, 4, 5}, func(i int) string {
	if i%2 == 0 {
		return "even"
	} else {
		return "odd"
	}
}))) // {"even":[2,4], "odd":[1,3,5]}

// Set operation
fmt.Println(Union([]int{1, 2, 3}, []int{3, 4, 5}))     // [1, 2, 3, 4, 5]
fmt.Println(Intersect([]int{1, 2, 3}, []int{3, 4, 5})) // [3]
fmt.Println(Diff([]int{1, 2, 3}, []int{3, 4, 5}))      // [1, 2]
fmt.Println(Uniq([]int{1, 1, 2, 2, 3}))                // [1, 2, 3]
fmt.Println(Dup([]int{1, 1, 2, 2, 3}))                 // [1, 2]

// Re-order operation
s1 := []int{5, 1, 2, 3, 4}
s2, s3, s4 := Clone(s1), Clone(s1), Clone(s1)
Sort(s1)
SortBy(s2, func(i, j int) bool { return i > j })
StableSortBy(s3, func(i, j int) bool { return i > j })
Reverse(s4)
fmt.Println(s1) // [1, 2, 3, 4, 5]
fmt.Println(s2) // [5, 4, 3, 2, 1]
fmt.Println(s3) // [5, 4, 3, 2, 1]
fmt.Println(s4) // [4, 3, 2, 1, 5]
Output:

[1 2 3 4 5]
[2 4]
15
true
false
true
true
false
2
2
1
2
5
[1 2 3 4]
[5 3]
[1 2]
[4 5]
[2 3]
[[1 2] [3 4] [5]]
[[1 2 3] [4 5]]
[1 2 3 4 5]
[1 2 3 4 5]
[2 4] [1 3 5]
5
1
1 5
15
{"1":1,"2":2,"3":3,"4":4,"5":5}
{"1":1,"2":2,"3":3,"4":4,"5":5}
{"even":[2,4],"odd":[1,3,5]}
[1 2 3 4 5]
[3]
[1 2]
[1 2 3]
[1 2]
[1 2 3 4 5]
[5 4 3 2 1]
[5 4 3 2 1]
[4 3 2 1 5]

Index ΒΆ

Examples ΒΆ

Constants ΒΆ

This section is empty.

Variables ΒΆ

This section is empty.

Functions ΒΆ

func All ΒΆ

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

All determines whether all elements of the slice s satisfy the predicate f.

πŸš€ EXAMPLE:

All([]int{1, 2, 3}, func(x int) bool { return x > 0 }) ⏩ true

func Any ΒΆ

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

Any determines whether any (at least one) element of the slice s satisfies the predicate f.

Any supports short-circuit evaluation.

πŸš€ EXAMPLE:

Any([]int{1, 2, 3}, func(x int) bool { return x > 2 }) ⏩ true

πŸ’‘ HINT:

  • Use All to known whether all elements satisfies the predicate f
  • Use CountBy to known how many elements satisfies the predicate f

func Avg ΒΆ

func Avg[T constraints.Number](s []T) float64

Avg returns the arithmetic mean of the elements of slice s.

πŸš€ EXAMPLE:

Avg([]int{1, 2, 3, 4, 5})      ⏩ 3.0
Avg([]float64{1, 2, 3, 4, 5})  ⏩ 3.0

πŸ’‘ AKA: Mean, Average

func AvgBy ΒΆ

func AvgBy[T any, N constraints.Number](s []T, f func(T) N) float64

AvgBy applies function f to each element of slice s, returns the arithmetic mean of function result.

πŸ’‘ AKA: MeanBy, AverageBy

func Chunk ΒΆ

func Chunk[S ~[]T, T any](s S, size int) []S

Chunk splits a slice into length-n chunks and returns chunks by a newly allocated slice.

The last chunk will be shorter if n does not evenly divide the length of the list.

πŸš€ EXAMPLE:

Chunk([]int{0, 1, 2, 3, 4}, 2) ⏩ [][]int{{0, 1}, {2, 3}, {4}}

πŸ’‘ HINT:

  • If you want to split list into n chunks, use function Divide.
  • This function returns sub-slices of original slice, if you modify the sub-slices, the original slice is modified too. Use ChunkClone to prevent this.
  • Use Flatten to restore chunks to flat slice.

πŸ’‘ AKA: Page, Pagination

func ChunkClone ΒΆ

func ChunkClone[S ~[]T, T any](s S, size int) []S

ChunkClone is variant of function Chunk. It clones the original slice before chunking it.

func Clone ΒΆ

func Clone[S ~[]T, T any](s S) S

Clone returns a shallow copy of the slice. If the given slice is nil, nil is returned.

πŸš€ EXAMPLE:

Clone([]int{1, 2, 3}) ⏩ []int{1, 2, 3}
Clone([]int{})        ⏩ []int{}
Clone[int](nil)       ⏩ nil

πŸ’‘ HINT: The elements are copied using assignment (=), so this is a shallow clone. If you want to do a deep clone, use CloneBy with an appropriate element clone function.

πŸ’‘ AKA: Copy

func CloneBy ΒΆ

func CloneBy[S ~[]T, T any](s S, f func(T) T) S

CloneBy is variant of Clone, it returns a copy of the slice. Elements are copied using function clone. If the given slice is nil, nil is returned.

πŸ’‘ AKA: CopyBy

func Compact ΒΆ

func Compact[S ~[]T, T comparable](s S) S

Compact removes all zero values from given slice s, returns a newly allocated slice.

πŸš€ EXAMPLE:

Compact([]int{0, 1, 2, 0, 3, 0, 0})     ⏩ []int{1, 2, 3}
Compact([]string{"", "foo", "", "bar"}) ⏩ []string{"foo", "bar"}

πŸ’‘ HINT: See github.com/bytedance/gg/gvalue.Zero for details of zero value.

func Concat ΒΆ

func Concat[S ~[]T, T any](ss ...S) S

Concat concatenates slices in order.

πŸš€ EXAMPLE:

Concat([]int{0}, []int{1, 2}, []int{3, 4}) ⏩ []int{0, 1, 2, 3, 4}

πŸ’‘ AKA: Merge, Connect

func Contains ΒΆ

func Contains[T comparable](s []T, v T) bool

Contains returns whether the element occur in slice.

πŸš€ EXAMPLE:

Contains([]int{0, 1, 2, 3, 4}, 1) ⏩ true
Contains([]int{0, 1, 2, 3, 4}, 5) ⏩ false
Contains([]int{}, 5)              ⏩ false

πŸ’‘ HINT:

  • Use ContainsAll, ContainsAny if you have multiple values to query
  • Use Index if you also want to know index of the found value
  • Use Any or Find if type of v is non-comparable

func ContainsAll ΒΆ

func ContainsAll[T comparable](s []T, vs ...T) bool

ContainsAll returns whether all of given elements occur in slice.

πŸš€ EXAMPLE:

s := []int{0, 1, 2, 3, 4}
ContainsAll(s, 0)    ⏩ true
ContainsAll(s, 5)    ⏩ false
ContainsAll(s, 0, 1) ⏩ true
ContainsAll(s, 0, 5) ⏩ false

func ContainsAny ΒΆ

func ContainsAny[T comparable](s []T, vs ...T) bool

ContainsAny returns whether any of given elements occur in slice.

πŸš€ EXAMPLE:

s := []int{0, 1, 2, 3, 4}
ContainsAny(s, 0)    ⏩ true
ContainsAny(s, 5)    ⏩ false
ContainsAny(s, 0, 1) ⏩ true
ContainsAny(s, 0, 5) ⏩ true

func Count ΒΆ

func Count[T comparable](s []T, v T) int

Count returns the times of value v that occur in slice s.

πŸš€ EXAMPLE:

Count([]string{"a", "b", "c"}, "a") ⏩ 1
Count([]int{0, 1, 2, 0, 5, 3}, 0)   ⏩ 2

πŸ’‘ HINT:

  • Use Contains if you just want to know whether the element exitss or not
  • Use CountBy if type of v is non-comparable

func CountBy ΒΆ

func CountBy[T any](s []T, f func(T) bool) int

CountBy returns the times of element in slice s that satisfy the predicate f.

πŸš€ EXAMPLE:

CountBy([]string{"a", "b", "c"}, func (v string) bool { return v < "b" }) ⏩ 1
CountBy([]int{0, 1, 2, 3, 4}, func (v int) bool { return v % i == 0 })    ⏩ 3

πŸ’‘ HINT: Use Any if you just want to know whether at least one element satisfies predicate f.

func CountValues ΒΆ

func CountValues[T comparable](s []T) map[T]int

CountValues returns the occurrences of each element in slice s.

πŸš€ EXAMPLE:

CountValues([]string{"a", "b", "b"}) ⏩ map[string]int{"a": 1, "b": 2}
CountValues([]int{0, 1, 2, 0, 1, 1}) ⏩ map[int]int{0: 2, 1: 3, 2: 1}

πŸ’‘ HINT:

func CountValuesBy ΒΆ

func CountValuesBy[K comparable, T any](s []T, f func(T) K) map[K]int

CountValuesBy returns the times of each element in slice s that satisfy the predicate f.

πŸš€ EXAMPLE:

CountValuesBy([]int{0, 1, 2, 3, 4}, func(v int) bool { return v%2 == 0 }) ⏩ map[bool]int{true: 3, false: 2}
type Foo struct{ v int }
foos := []Foo{{1}, {2}, {3}}
CountValuesBy(foos, func(v Foo) bool { return v.v%2 == 0 }) ⏩ map[bool]int{true: 1, false: 2}

func Diff ΒΆ

func Diff[S ~[]T, T comparable](s S, againsts ...S) S

Diff returns the difference of slice s against other slices as a newly allocated slice.

πŸ’‘ NOTE: If the result is an empty set, always return an empty slice instead of nil

πŸš€ EXAMPLE:

Diff([]int{1, 2, 3}, []int{3, 4, 5}) ⏩ []int{1, 2}
Diff([]int{1, 2, 3}, []int{4, 5, 6}) ⏩ []int{1, 2, 3}
Diff([]int{1, 2, 3}, []int{1, 2, 3}) ⏩ []int{}

πŸ’‘ HINT: if you need a set data structure, use github.com/bytedance/gg/collection/set.

func Divide ΒΆ

func Divide[S ~[]T, T any](s S, n int) []S

Divide splits a list into exactly n slices and returns chunks by a newly allocated slice.

The length of chunks will be different if n does not evenly divide the length of the slice.

πŸš€ EXAMPLE:

s := []int{0, 1, 2, 3, 4}
Divide(s, 2)       ⏩ [][]int{{0, 1, 2},  {3, 4}}
Divide(s, 3)       ⏩ [][]int{{0, 1}, {2, 3}, {4}}
Divide([]int{}, 2) ⏩ [][]int{{}, {}}

πŸ’‘ HINT:

  • If you want to split list into length-n chunks, use Chunk.
  • This function returns sub-slices of original slice, if you modify the sub-slices, the original slice is modified too. Use DivideClone to prevent this.
  • Use Flatten to restore chunks to flat slice.

πŸ’‘ AKA: Page, Pagination

func DivideClone ΒΆ

func DivideClone[S ~[]T, T any](s S, n int) []S

DivideClone is variant of function Divide. It clones the original slice before dividing it.

func Drop ΒΆ

func Drop[S ~[]T, T any](s S, n int) S

Drop drops the first n elements of slices s, returns the remaining part of slice, or empty slice if n > len(s).

πŸš€ EXAMPLE:

s := []int{1, 2, 3, 4, 5}
Drop(s, 0)  ⏩ []int{1, 2, 3, 4, 5}
Drop(s, 3)  ⏩ []int{4, 5}
Drop(s, 10) ⏩ []int{}

⚠️ WARNING: Panic when n < 0.

πŸ’‘ NOTE: This function returns sub-slices of original slice, if you modify the sub-slices, the original slice is modified too. Use DropClone to prevent this.

func DropClone ΒΆ

func DropClone[S ~[]T, T any](s S, n int) S

DropClone is variant of Drop.

func Dup ΒΆ

func Dup[S ~[]T, T comparable](s S) S

Dup returns the repeated elements of slice. The result are sorted in order of recurrence.

πŸš€ EXAMPLE:

Dup([]int{0, 1, 1, 1})    ⏩ []int{1}
Dup([]int{3, 2, 2, 3, 3}) ⏩ []int{2, 3} // in order of recurrence

πŸ’‘ HINT:

  • If type is not comparable, use DupBy.
  • If you need distinct elements, use Uniq.

πŸ’‘ AKA: Duplicate.

func DupBy ΒΆ

func DupBy[S ~[]T, K comparable, T any](s S, f func(T) K) S

DupBy returns the repeated elements of slice with key function f. The result is a newly allocated slice contains duplicate elements. The result are sorted in order of recurrence.

πŸš€ EXAMPLE:

type Foo struct{ Value int }
s := []Foo{{3}, {2}, {2}, {3}, {3}}
DupBy(s, func(v Foo) int { return v.Value }) ⏩ []Foo{{2}, {3}}

πŸ’‘ AKA: DuplicateBy.

func Equal ΒΆ

func Equal[T comparable](s1, s2 []T) bool

Equal returns whether two slices are equal.

πŸš€ EXAMPLE:

Equal([]int{1, 2, 3}, []int{1, 2, 3})    ⏩ true
Equal([]int{1, 2, 3}, []int{1, 2, 3, 4}) ⏩ false
Equal([]int{}, []int{})                  ⏩ true
Equal([]int{}, nil)                      ⏩ true

func EqualBy ΒΆ

func EqualBy[T any](s1, s2 []T, eq func(T, T) bool) bool

EqualBy returns whether two slices are equal by function eq.

πŸš€ EXAMPLE:

eq := gvalue.Equal[int]
EqualBy([]int{1, 2, 3}, []int{1, 2, 3}, eq)    ⏩ true
EqualBy([]int{1, 2, 3}, []int{1, 2, 3, 4}, eq) ⏩ false
EqualBy([]int{}, []int{}, eq)                  ⏩ true
EqualBy([]int{}, nil, eq)                      ⏩ true

func Filter ΒΆ

func Filter[S ~[]T, T any](s S, f func(T) bool) S

Filter applies predicate f to each element of slice s, returns those elements that satisfy the predicate f as a newly allocated slice.

πŸš€ EXAMPLE:

Filter([]int{0, 1, 2, 3}, gvalue.IsNotZero[int]) ⏩ []int{1, 2, 3}

πŸ’‘ HINT:

  • Use FilterMap if you also want to change the element during filtering.
  • If you need elements that do not satisfy f, use Reject
  • If you need both elements, use Partition

func FilterMap ΒΆ

func FilterMap[F, T any](s []F, f func(F) (T, bool)) []T

FilterMap does Filter and Map at the same time, applies function f to each element of slice s. f returns (T, bool):

  • If true ,the return value with type T will added to the result slice []T.
  • If false, the return value with type T will be dropped.

πŸš€ EXAMPLE:

f := func(i int) (string, bool) { return strconv.Itoa(i), i != 0 }
FilterMap([]int{1, 2, 3, 0, 0}, f) ⏩ []string{"1", "2", "3"}

πŸ’‘ HINT: Use TryFilterMap if function f returns (T, error).

func Find ΒΆ

func Find[T any](s []T, f func(T) bool) goption.O[T]

Find returns the possible first element of slice that satisfies predicate f.

πŸš€ EXAMPLE:

s := []int{0, 1, 2, 3, 4}
Find(s, func(v int) bool { return v > 0 }) ⏩ goption.OK(1)
Find(s, func(v int) bool { return v < 0 }) ⏩ goption.Nil[int]()

πŸ’‘ HINT:

  • Use Contains if you just want to know whether the value exists
  • Use IndexBy if you want to know the index of value
  • Use FindRev if you want to find in reverse order
  • Use Count if you want to count the occurrences of element

πŸ’‘ AKA: Search

func FindRev ΒΆ

func FindRev[T any](s []T, f func(T) bool) goption.O[T]

FindRev is a variant of Find in reverse order.

πŸš€ EXAMPLE:

s := []int{0, 1, 2, 3, 4}
FindRev(s, func(v int) bool { return v > 0 }) ⏩ goption.OK(4)
FindRev(s, func(v int) bool { return v < 0 }) ⏩ goption.Nil[int]()

func First ΒΆ

func First[T any](s []T) goption.O[T]

First returns the possible first element of slice s. If the given slice is empty, goption.Nil[T]() is returned.

πŸš€ EXAMPLE:

First([]int{4, 3, 1, 4}) ⏩ goption.OK(4)
First([]int{})           ⏩ goption.Nil[int]()

πŸ’‘ HINT: Use Get to access element at any index.

πŸ’‘ AKA: Head

func FlatMap ΒΆ

func FlatMap[F, T any](s []F, f func(F) []T) []T

FlatMap applies function f to each element of slice s with type F. Results of f are flatten and returned as a newly allocated slice with type T.

πŸš€ EXAMPLE:

type Site struct{ urls []string }
func (s Site) URLs() []string { return s.urls }

sites := []Site{
	{[]string{"url1", "url2"}},
	{[]string{"url3", "url4"}},
}

FlatMap(sites, Site.URLs) ⏩ []string{"url1", "url2", "url3", "url4"}

πŸ’‘ HINT:

  • Use Flatten if the element of given slice is also slice.
  • Use FilterMap if you want to ignore some element during mapping

func Flatten ΒΆ

func Flatten[S ~[]T, T any](s []S) S

Flatten collapses a tow-dimension slice to one dimension.

πŸš€ EXAMPLE:

Flatten([][]int{{0}, {1, 2}, {3, 4}}) ⏩ []int{0, 1, 2, 3, 4}

πŸ’‘ HINT: Use FlatMap if you want to flatten non-slice elements.

func Fold ΒΆ

func Fold[T1, T2 any](s []T1, f func(T2, T1) T2, init T2) T2

Fold applies function f cumulatively to each element of slice s, so as to fold the slice to a single value. An init element is needed as the initial value of accumulation. If the given slice is empty, the init element is returned.

πŸš€ EXAMPLE:

s := []int{0, 1, 2, 3}
Fold(s, gvalue.Add[int], 4)       ⏩ 10
Fold(s, gvalue.Add[int], 2)       ⏩ 8
Fold([]int{}, gvalue.Add[int], 1) ⏩ 1

func ForEach ΒΆ

func ForEach[T any](s []T, f func(v T))

ForEach applies function f to each element of slice s.

πŸ’‘ HINT: Use ForEachIndexed If you want to get element with index.

func ForEachIndexed ΒΆ

func ForEachIndexed[T any](s []T, f func(i int, v T))

ForEachIndexed applies function f to each element of slice s. The argument i of function f represents the zero-based index of that element of slice.

func Get ΒΆ

func Get[T any, I constraints.Integer](s []T, n I) goption.O[T]

Get returns the possible element at index n.

[Negative index] is supported. For example:

  • Get(s, 0) returns the First element
  • Get(s, -1) returns the Last element

πŸš€ EXAMPLE:

s := []int{1, 2, 3, 4}
Get(s, 0)  ⏩ goption.OK(1)
Get(s, 1)  ⏩ goption.OK(2)
Get(s, -1) ⏩ goption.OK(4)
Get(s, -2) ⏩ goption.OK(3)

πŸ’‘ AKA: Nth, At, Access, ByIndex, Load

func GroupBy ΒΆ

func GroupBy[S ~[]T, K comparable, T any](s S, f func(T) K) map[K]S

GroupBy adjacent elements according to key returned by function f.

πŸš€ EXAMPLE:

GroupBy([]int{1, 2, 3, 4},
func(v int) string {
    return gcond.If(v%2 == 0, "even", "odd")
})

⏩

map[string][]int{
    "odd": {1, 3},
    "even": {2, 4},
}

πŸ’‘ HINT: If function f returns bool, use Partition instead.

func Index ΒΆ

func Index[T comparable](s []T, e T) goption.O[int]

Index returns the index of the first occurrence of element in slice s, or nil if not present.

πŸš€ EXAMPLE:

s := []string{"a", "b", "b", "d"}
Index(s, "b") ⏩ goption.OK(1)
Index(s, "e") ⏩ goption.Nil[int]()

πŸ’‘ HINT:

  • Use IndexBy if complex comparison logic is required (instead of just ==)
  • Use Contains if you just want to know whether the value exists
  • Use IndexRev if you want to index element in reverse order.

func IndexBy ΒΆ

func IndexBy[T any](s []T, f func(T) bool) goption.O[int]

IndexBy is variant of Index, returns the first index of element that satisfying predicate f, or nil if none do.

func IndexRev ΒΆ

func IndexRev[T comparable](s []T, e T) goption.O[int]

IndexRev is a variant of Index in reverse order.

πŸš€ EXAMPLE:

s := []string{"a", "b", "b", "d"}
IndexRev(s, "b") ⏩ goption.OK(2)
IndexRev(s, "e") ⏩ goption.Nil[int]()

func IndexRevBy ΒΆ

func IndexRevBy[T any](s []T, f func(T) bool) goption.O[int]

IndexRevBy is variant of IndexRev, returns the first index of element that satisfying predicate f, or nil if none do.

func Indirect ΒΆ

func Indirect[T any](s []*T) []T

Indirect returns the values pointed to by the pointers. If the element is nil, filter it out of the returned slice.

πŸš€ EXAMPLE:

v1, v2 := 1, 2
Indirect([]*int{ &v1, &v2, nil})  ⏩ []int{1, 2}

πŸ’‘ HINT: If you want to replace nil pointer with default value, use IndirectOr.

func IndirectOr ΒΆ

func IndirectOr[T any](s []*T, fallback T) []T

IndirectOr safely dereferences slice of pointers. If the pointer is nil, returns the value fallback instead.

πŸš€ EXAMPLE:

v1, v2 := 1, 2
IndirectOr([]*int{ &v1, &v2, nil}, -1)  ⏩ []int{1, 2, -1}

func Insert ΒΆ

func Insert[S ~[]T, T any, I constraints.Integer](s S, pos I, vs ...T) S

Insert inserts elements vs before position pos, returns a newly allocated slice. [Negative index] is supported.

  • Insert(x, 0, ...) inserts at the front of the slice
  • Insert(x, len(x), ...) is equivalent to append(x, ...)
  • Insert(x, -1, ...) is equivalent to Insert(x, len(x)-1, ...)

πŸš€ EXAMPLE:

s := []int{0, 1, 2, 3}
Insert(s, 0, 99)      ⏩ []int{99, 0, 1, 2, 3}
Insert(s, 0, 98, 99)  ⏩ []int{98, 99, 0, 1, 2, 3}
Insert(s, 4, 99)      ⏩ []int{0, 1, 2, 3, 99}
Insert(s, 1, 99)      ⏩ []int{0, 99, 1, 2, 3}
Insert(s, -1, 99)     ⏩ []int{0, 1, 2, 99, 3}

func Intersect ΒΆ

func Intersect[S ~[]T, T comparable](ss ...S) S

Intersect returns the intersection of slices as a newly allocated slice.

πŸ’‘ NOTE: If the result is an empty set, always return an empty slice instead of nil

πŸš€ EXAMPLE:

Intersect([]int{1, 2, 3}, []int{2, 3, 4}) ⏩ []int{2, 3}
Intersect([]int{1, 2, 3}, []int{4, 5, 6}) ⏩ []int{}
Intersect([]int{1, 2, 3}, []int{1, 2, 3}) ⏩ []int{1, 2, 3}

πŸ’‘ HINT: if you need a set data structure, use github.com/bytedance/gg/collection/set.

func Last ΒΆ

func Last[T any](s []T) goption.O[T]

Last returns the possible last element of slice s. If the given slice is empty, goption.Nil[T]() is returned.

πŸš€ EXAMPLE:

Last([]int{4, 3, 1, 5}) ⏩ goption.OK(5)
Last([]int{})           ⏩ goption.Nil[int]()

πŸ’‘ HINT: Use Get to access element at any index.

πŸ’‘ AKA: Tail

func Len ΒΆ

func Len[T any](s []T) int

Len returns the length of slice s.

πŸ’‘ HINT: This function is designed for high-order function, because the builtin function can not be used as function pointer. For example, if you want to get the total length of a 2D slice:

var s [][]int
total1 := SumBy(s, len)      // ❌ERROR❌ len (built-in) must be called
total2 := SumBy(s, Len[int]) // OK

func Map ΒΆ

func Map[F, T any](s []F, f func(F) T) []T

Map applies function f to each element of slice s with type F. Results of f are returned as a newly allocated slice with type T.

πŸš€ EXAMPLE:

Map([]int{1, 2, 3}, strconv.Itoa) ⏩ []string{"1", "2", "3"}
Map([]int{}, strconv.Itoa)        ⏩ []string{}
Map(nil, strconv.Itoa)            ⏩ []string{}

πŸ’‘ HINT:

  • Use FilterMap if you also want to ignore some element during mapping.
  • Use TryMap if function f may fail (return (T, error))

func Max ΒΆ

func Max[T constraints.Ordered](s []T) goption.O[T]

Max returns maximum element of slice s. If the given slice is empty, goption.Nil[T]() is returned.

πŸš€ EXAMPLE:

Max([]int{0, 1, 4, 3, 1, 4}) ⏩ goption.OK(4)
Max([]int{})                 ⏩ goption.Nil[int]()

πŸ’‘ HINT: If type is not orderable, use MaxBy.

func MaxBy ΒΆ

func MaxBy[T any](s []T, less func(T, T) bool) goption.O[T]

MaxBy returns the maximum element of slice s determined by function less. If the given slice is empty, goption.Nil[T]() is returned.

πŸš€ EXAMPLE:

type Foo struct { Value int }
less := func(x, y Foo) bool { return x.Value < y.Value }
s := []Foo{{10}, {1}, {-1}, {100}, {3}}
MaxBy(s, less) ⏩ goption.OK(Foo{100})

func Merge ΒΆ

func Merge[S ~[]T, T any](ss ...S) S

Merge is alias of Concat.

func Min ΒΆ

func Min[T constraints.Ordered](s []T) goption.O[T]

Min returns the minimum element of slices s. If the given slice is empty, goption.Nil[T]() is returned.

πŸš€ EXAMPLE:

Min([]int{1, 4, 3, 1, 4}) ⏩ goption.OK(1)
Min([]int{})              ⏩ goption.Nil[int]()

πŸ’‘ HINT: If type is not orderable, use MinBy.

func MinBy ΒΆ

func MinBy[T any](s []T, less func(T, T) bool) goption.O[T]

MinBy returns the minimum element of slices s determined by function less. If the given slice is empty, goption.Nil[T]() is returned.

πŸš€ EXAMPLE:

type Foo struct { Value int }
less := func(x, y Foo) bool { return x.Value < y.Value }
MinBy([]Foo{{10}, {1}, {-1}, {100}, {3}}, less) ⏩ goption.OK(Foo{-1})

func MinMax ΒΆ

func MinMax[T constraints.Ordered](s []T) goption.O[tuple.T2[T, T]]

MinMax returns both minimum and maximum elements of slice s. If the given slice is empty, goption.Nil[tuple.T2[T, T]]() is returned.

πŸš€ EXAMPLE:

MinMax([]int{})                 ⏩ goption.Nil[int]()
MinMax([]int{1})                ⏩ goption.OK(tuple.T2{1, 1})
MinMax([]int{0, 1, 4, 3, 1, 4}) ⏩ goption.OK(tuple.T2{0, 4})

πŸ’‘ HINT: If type is not orderable, use MinMaxBy.

πŸ’‘ AKA: Bound

func MinMaxBy ΒΆ

func MinMaxBy[T any](s []T, less func(T, T) bool) goption.O[tuple.T2[T, T]]

MinMaxBy returns both minimum and maximum elements of slice s. If the given slice is empty, goption.Nil[tuple.T2[T, T]]() is returned.

πŸš€ EXAMPLE:

type Foo struct { Value int }
less := func(x, y Foo) bool { return x.Value < y.Value }
MinMaxBy([]Foo{{10}, {1}, {-1}, {100}, {3}}, less) ⏩ goption.OK(tuple.T2{Foo{-1}, Foo{100}})

πŸ’‘ NOTE: The returned min and max elements may be the same object when each element of the slice is equal

πŸ’‘ AKA: BoundBy

func Of ΒΆ

func Of[T any](v ...T) []T

Of creates a slice from variadic arguments. If no argument given, an empty (non-nil) slice []T{} is returned.

πŸ’‘ HINT: This function is used to omit verbose types like "[]LooooongTypeName{}" when constructing slices.

πŸš€ EXAMPLE:

Of(1, 2, 3) ⏩ []int{1, 2, 3}
Of(1)       ⏩ []int{1}
Of[int]()   ⏩ []int{}

func Partition ΒΆ

func Partition[S ~[]T, T any](s S, f func(T) bool) (S, S)

Partition applies predicate f to each element of slice s, divides elements into 2 parts: satisfy f and do not satisfy f.

πŸš€ EXAMPLE:

Partition([]int{0, 1, 2, 3}, gvalue.IsNotZero[int]) ⏩ []int{1, 2, 3}, []int{0}

πŸ’‘ HINT:

  • Use Filter or Reject if you need only one of the return values
  • Use Chunk or Divide if you want to divide elements by index

func PtrOf ΒΆ

func PtrOf[T any](s []T) []*T

PtrOf returns pointers that point to equivalent elements of slice s. ([]T β†’ []*T).

πŸš€ EXAMPLE:

PtrOf([]int{1, 2, 3}) ⏩ []*int{ (*int)(1), (*int)(2), (*int)(3) },

⚠️ WARNING: The returned pointers do not point to elements of the original slice, user CAN NOT modify the element by modifying the pointer.

func Range ΒΆ

func Range[I constraints.Number](start, stop I) []I

Range is a variant of RangeWithStep, with predefined step 1.

πŸš€ EXAMPLE:

Range(0, 0)    ⏩ []int{}
Range(0, -5)   ⏩ []int{}
Range(0, 5)    ⏩ []int{0, 1, 2, 3, 4}

func RangeWithStep ΒΆ

func RangeWithStep[I constraints.Number](start, stop, step I) []I

RangeWithStep returns a slice of numbers from start (inclusive) to stop (exclusive) by step. If the interval does not exist, RangeWithStep returns an empty slice. If the step is positive, the returned slice is in ascending order. If the step is negative, the returned slice is in descending order.

πŸš€ EXAMPLE:

RangeWithStep(0, 0, 2)     ⏩ []int{}
RangeWithStep(0, -5, -1)   ⏩ []int{0, -1, -2, -3, -4}
RangeWithStep(0, 5, 2)     ⏩ []int{0, 2, 4}
RangeWithStep(0, 5, 3)     ⏩ []int{0, 3}
RangeWithStep(0.5, 2, 0.5) ⏩ []float64{0.5, 1, 1.5}

func Reduce ΒΆ

func Reduce[T any](s []T, f func(T, T) T) goption.O[T]

Reduce is a variant of Fold, use possible first element of slice as the initial value of accumulation. If the given slice is empty, goption.Nil[T]() is returned.

πŸš€ EXAMPLE:

Reduce([]int{0, 1, 2, 3}, gvalue.Add[int]) ⏩ goption.OK(6)
Reduce([]int{}, gvalue.Add[int])           ⏩ goption.Nil[int]()

πŸ’‘ HINT: Calculate the maximum value is only for example, you can directly use function Max.

func Reject ΒΆ

func Reject[S ~[]T, T any](s S, f func(T) bool) S

Reject applies predicate f to each element of slice s, returns those elements that do not satisfy the predicate f as a newly allocated slice.

πŸš€ EXAMPLE:

Reject([]int{0, 1, 2, 3}, gvalue.IsZero[int]) ⏩ []int{1, 2, 3}

πŸ’‘ HINT:

  • If you need elements that satisfy f, use Filter
  • If you need both elements, use Partition

func Remove ΒΆ

func Remove[S ~[]T, T comparable](s S, v T) S

Remove removes all element v from the slice s, returns a newly allocated slice.

πŸš€ EXAMPLE:

Remove([]int{0, 1, 2, 3, 4}, 3)    ⏩ []int{0, 1, 2, 4}
Remove([]int{0, 1, 3, 2, 3, 4}, 3) ⏩ []int{0, 1, 2, 4}

πŸ’‘ HINT:

  • Use Compact if you just want to remove zero value.
  • Use RemoveIndex if you want to remove value by index

πŸ’‘ AKA: Delete

func RemoveIndex ΒΆ

func RemoveIndex[S ~[]T, I constraints.Integer, T any](s S, index I) S

RemoveIndex removes the element at index i from slice s and returns a newly allocated slice. If s[i] does not exist or is invalid, this function just clone the original slice. [Negative index] is supported.

  • RemoveIndex(x, 0) 🟰 Clone(s[1:])
  • RemoveIndex(x, -1) 🟰 Clone(s[0:len(x)-1])
  • RemoveIndex(x, len(x)) 🟰 Clone(s)

πŸš€ EXAMPLE:

RemoveIndex([]int{0, 1, 2, 3, 4}, 3)    ⏩ []int{0, 1, 2, 4}
RemoveIndex([]int{0, 1, 2, 3, 4}, -1)   ⏩ []int{0, 1, 2, 3}
RemoveIndex([]int{0, 1, 2, 3, 4}, 0)    ⏩ []int{1, 2, 3, 4}
RemoveIndex([]int{0, 1, 2, 3, 4}, 100)  ⏩ []int{0, 1, 2, 3, 4}

πŸ’‘ Hint: This function has O(n) time complexity and ALWAYS returns a newly allocated slice.

πŸ’‘ HINT: Use Remove if you want to remove elements by value

πŸ’‘ AKA: DeleteIndex

func Repeat ΒΆ

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

Repeat returns a slice with value v repeating exactly n times. The result is an empty slice if n is 0.

⚠️ WARNING: The function panics if n is negative.

πŸš€ EXAMPLE:

Repeat(123, -1) ⏩ ❌PANIC❌
Repeat(123, 0)  ⏩ []int{}
Repeat(123, 3)  ⏩ []int{123, 123, 123}

πŸ’‘ HINT: The result slice contains shallow copy of element v. Use RepeatBy with a copier if deep copy is necessary.

func RepeatBy ΒΆ

func RepeatBy[T any](fn func() T, n int) []T

RepeatBy returns a slice with elements generated by calling fn exactly n times. The result is an empty slice if n is 0.

⚠️ WARNING:

  • The function panics if n is negative.

πŸš€ EXAMPLE:

fn := func() *int { v := 123; return &v }
RepeatBy(fn, -1) ⏩ ❌PANIC❌
RepeatBy(fn, 0)  ⏩ []*int{}
RepeatBy(fn, 3)  ⏩ []*int{ &int(123), &int(123), &int(123) } // different addresses!

func Reverse ΒΆ

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

Reverse reverses the elements of slices.

πŸ’‘ HINT: If you want to reverse in a newly allocated slice, use ReverseClone.

func ReverseClone ΒΆ

func ReverseClone[S ~[]T, T any](s S) S

ReverseClone is variant of Reverse. It clones the original slice before reversing it.

func Shuffle ΒΆ

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

Shuffle pseudo-randomizes the order of elements.

Shuffle is 2x ~ 40x(parallel) faster than math/rand.Shuffle.

πŸ’‘ HINT: If you want to shuffle in a newly allocated slice, use ShuffleClone .

func ShuffleClone ΒΆ

func ShuffleClone[S ~[]T, T any](s S) S

ShuffleClone is variant of Shuffle. It clones the original slice before shuffling it.

func Slice ΒΆ

func Slice[S ~[]T, I constraints.Integer, T any](s S, start, end I) S

Slice returns a sub-slice of the slice S that contains the elements starting from the start-th element up to but not including the end-th element "[start:end)". In other words, it is safer replacement of [Slice Expression].

  • Slice(s, 0, 3) 🟰 s[:3]
  • Slice(s, 1, 3) 🟰 s[1:3]

[Negative index] is supported:

  • Slice(s, -3, -1) 🟰 s[len(s)-3:len(s)-1]
  • Slice(s, -3, 0) 🟰 s[len(s)-3:] specially, the 0 at the end implies the end slice.

πŸš€ EXAMPLE:

s := []int{1, 2, 3, 4, 5}
Slice(s, 0, 3)     ⏩ []int{1, 2, 3}
Slice(s, 1, 3)     ⏩ []int{2, 3}
Slice(s, 0, 0)     ⏩ []int{}
Slice(s, 0, 100)   ⏩ []int{1, 2, 3, 4, 5}  // won't PANIC even out of range
Slice(s, 100, 99)  ⏩ []int{}               // won't PANIC even out of range
Slice(s, -3, -1)   ⏩ []int{3, 4}           // equal to Slice(s, 2, 4) and Slice(s, -3, 4)
Slice(s, -1, 0)    ⏩ []int{5}              // specially, the 0 at the end implies the end slice

πŸ’‘ HINT: This function returns sub-slices of original slice, if you modify the sub-slices, the original slice is modified too. Use SliceClone to prevent this.

func SliceClone ΒΆ

func SliceClone[S ~[]T, I constraints.Integer, T any](s S, start, end I) S

SliceClone is variant of Slice.

func Sort ΒΆ

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

Sort sorts elements of slice in ascending order (from small to large).

πŸš€ EXAMPLE:

s := []int{1, 3, 2, 4}
Sort(s) ⏩ []int{1, 2, 3, 4}

πŸ’‘ HINT:

πŸ’‘ AKA: Order

func SortBy ΒΆ

func SortBy[T any](s []T, less func(T, T) bool)

SortBy sorts elements of slices i with function less.

πŸ’‘ AKA: OrderBy

func SortClone ΒΆ

func SortClone[S ~[]T, T constraints.Ordered](s S) S

SortClone is variant of Sort. It clones the original slice before sorting it.

func SortCloneBy ΒΆ

func SortCloneBy[S ~[]T, T any](s S, less func(T, T) bool) S

SortCloneBy is variant of function SortBy. It clones the original slice before sorting it.

func StableSortBy ΒΆ

func StableSortBy[T any](s []T, less func(T, T) bool)

StableSortBy is variant of SortBy, it keeps the original order of equal elements when sorting.

func Sum ΒΆ

func Sum[T constraints.Number](s []T) T

Sum returns the arithmetic sum of the elements of slice s.

πŸš€ EXAMPLE:

Sum([]int{1, 2, 3, 4, 5})     ⏩ 15
Sum([]float64{1, 2, 3, 4, 5}) ⏩ 15.0

⚠️ WARNING: The returned type is still T, it may overflow for smaller types (such as int8, uint8).

func SumBy ΒΆ

func SumBy[T any, N constraints.Number](s []T, f func(T) N) N

SumBy applies function f to each element of slice s, returns the arithmetic sum of function result.

func Take ΒΆ

func Take[S ~[]T, I constraints.Integer, T any](s S, n I) S

Take returns the first n elements of slices s if 0 <= n <= len(s), or slice itself if n > len(s). If -len(s) <= n < 0, returns the last -n elements of slice s, or slice itself if n < -len(s).

πŸš€ EXAMPLE:

s := []int{1, 2, 3, 4, 5}
Take(s, 0)   ⏩ []int{}
Take(s, 3)   ⏩ []int{1, 2, 3}
Take(s, 10)  ⏩ []int{1, 2, 3, 4, 5}
Take(s, -1)  ⏩ []int{5}
Take(s, -3)  ⏩ []int{3, 4, 5}
Take(s, -10) ⏩ []int{1, 2, 3, 4, 5}

πŸ’‘ HINT: This function returns sub-slices of original slice, if you modify the sub-slices, the original slice is modified too. Use TakeClone to prevent this.

func TakeClone ΒΆ

func TakeClone[S ~[]T, I constraints.Integer, T any](s S, n I) S

TakeClone is variant of Take.

func ToMap ΒΆ

func ToMap[T, V any, K comparable](s []T, f func(T) (K, V)) map[K]V

ToMap collects elements of slice to map, both map keys and values are produced by mapping function f.

πŸš€ EXAMPLE:

type Foo struct {
	ID   int
	Name string
}
mapper := func(f Foo) (int, string) { return f.ID, f.Name }
ToMap([]Foo{}, mapper) ⏩ map[int]string{}
s := []Foo{{1, "one"}, {2, "two"}, {3, "three"}}
ToMap(s, mapper)       ⏩ map[int]string{1: "one", 2: "two", 3: "three"}

func ToMapValues ΒΆ

func ToMapValues[T any, K comparable](s []T, f func(T) K) map[K]T

ToMapValues collects elements of slice to values of map, the map keys are produced by mapping function f.

πŸš€ EXAMPLE:

type Foo struct {
    ID int
}
id := func(f Foo) int { return f.ID }
ToMapValues([]Foo{}, id)                    ⏩ map[int]Foo{}
ToMapValues([]Foo{ {1}, {2}, {1}, {3}}, id) ⏩ map[int]Foo{1: {1}, 2: {2}, 3: {3}}

πŸ’‘ AKA: Kotlin's associateBy

func TryFilterMap ΒΆ

func TryFilterMap[F, T any](s []F, f func(F) (T, error)) []T

TryFilterMap is a variant of FilterMap that allows function f to fail (return error).

πŸš€ EXAMPLE:

TryFilterMap([]string{"1", "2", "3"}, strconv.Atoi) ⏩ []int{1, 2, 3}
TryFilterMap([]string{"1", "2", "a"}, strconv.Atoi) ⏩ []int{1, 2}

func TryMap ΒΆ

func TryMap[F, T any](s []F, f func(F) (T, error)) gresult.R[[]T]

TryMap is a variant of Map that allows function f to fail (return error).

πŸš€ EXAMPLE:

TryMap([]string{"1", "2", "3"}, strconv.Atoi) ⏩ gresult.OK([]int{1, 2, 3})
TryMap([]string{"1", "2", "a"}, strconv.Atoi) ⏩ gresult.Err("strconv.Atoi: parsing \"a\": invalid syntax")
TryMap([]string{}, strconv.Atoi)              ⏩ gresult.OK([]int{})

πŸ’‘ HINT: Use TryFilterMap if you want to ignore error during mapping.

func TypeAssert ΒΆ

func TypeAssert[To, From any](s []From) []To

TypeAssert converts a slice from type From to type To by type assertion.

πŸš€ EXAMPLE:

TypeAssert[int]([]any{1, 2, 3, 4})   ⏩ []int{1, 2, 3, 4}
TypeAssert[any]([]int{1, 2, 3, 4})   ⏩ []any{1, 2, 3, 4}
TypeAssert[int64]([]int{1, 2, 3, 4}) ⏩ ❌PANIC❌

⚠️ WARNING:

func Union ΒΆ

func Union[S ~[]T, T comparable](ss ...S) S

Union returns the unions of slices as a newly allocated slices.

πŸ’‘ NOTE: If the result is an empty set, always return an empty slice instead of nil

πŸš€ EXAMPLE:

Union([]int{1, 2, 3}, []int{3, 4, 5}) ⏩ []int{1, 2, 3, 4, 5}
Union([]int{1, 2, 3}, []int{})        ⏩ []int{1, 2, 3}
Union([]int{}, []int{3, 4, 5})        ⏩ []int{3, 4, 5}

πŸ’‘ HINT: if you need a set data structure, use github.com/bytedance/gg/collection/set.

func Uniq ΒΆ

func Uniq[S ~[]T, T comparable](s S) S

Uniq returns the distinct elements of slice. Elements are ordered by their first occurrence.

πŸš€ EXAMPLE:

Uniq([]int{0, 1, 4, 3, 1, 4}) ⏩ []int{0, 1, 4, 3}

πŸ’‘ HINT:

  • If type is not comparable, use UniqBy.
  • If you need duplicate elements, use Dup.

πŸ’‘ AKA: Distinct, Dedup, Unique

func UniqBy ΒΆ

func UniqBy[S ~[]T, K comparable, T any](s S, f func(T) K) S

UniqBy returns the distinct elements of slice with key function f. The result is a newly allocated slice without duplicate elements.

πŸš€ EXAMPLE:

type Foo struct{ Value int }
s := []Foo{{0}, {1}, {4}, {3}, {1}, {4}}
UniqBy(s, func(v Foo) int { return v.Value }) ⏩ []Foo{{0}, {1}, {4}, {3}}

πŸ’‘ AKA: DistinctBy, DedupBy.

Types ΒΆ

This section is empty.

Jump to

Keyboard shortcuts

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