English | 简体中文
go-collection
provides developers with a convenient set of functions for working with common slices, maps, and arrays data. These functions are based on the generic types of Go 1.18, which makes it easier to use them without annoying type assertions. In addition to using these functions directly, it also supports method chaining.
collect.Reduce(collect.Filter(collect.Map([]int{1, 2, 3}, fn), fn), fn)
Equivalent to:
collect.UseSlice([]int{1, 2, 3}).Map(fn).Filter(fn).Reduce(fn)
go get -u github.com/sxyazi/go-collection
Then import it
import collect "github.com/sxyazi/go-collection"
Its API is very simple and if you have used other similar packages, you should be able to get started with it in a few minutes. For convenience, they are described below in function form.
The corresponding chained function is collect.UseSlice()
-
Len
gets the length of the sliceExamples
d1 := []int{1, 2, 3} collect.Len(d1) // 3 d2 := []string{"a", "b", "c"} collect.Len(d2) // 3
-
Each
iterates over each element in the sliceExamples
d := []float64{1, 2, 3} collect.Each(d, func(value float64, index int) { fmt.Println(index, value) })
-
Empty
checks if the slice is emptyExamples
var d []int collect.Empty(d) // true
-
Same
checks if the contents of two slices are the sameExamples
d1 := []int{1, 2, 3} d2 := []int{1, 2, 3} collect.Same(d1, d2) // true d3 := [][]int{{1, 2, 3}, {4, 5, 6}} d4 := [][]int{{1, 2, 3}, {4, 5, 6}} collect.Same(d3, d4) // true
-
First
gets the first element of the sliceExamples
d1 := []int{1, 2, 3} value, ok := collect.First(d1) // 1, true var d2 []int value, ok = collect.First(d2) // 0, false
-
Last
gets the last element of the sliceExamples
d1 := []int{1, 2, 3} value, ok := collect.Last(d1) // 3, true var d2 []int value, ok = collect.Last(d2) // 0, false
-
Index
gets the index of the specified element in the slice, and returns -1 if it does not exist.Examples
d1 := []int{1, 2, 3} collect.Index(d1, 2) // 1 s1 := []string{"a", "b", "c"} s2 := []string{"d", "e", "f"} collect.Index([][]string{s1, s2}, s2) // 1
-
Contains
checks if the slice contains the specified elementExamples
d1 := []int{1, 2, 3} collect.Contains(d1, 2) // true s1 := []string{"a", "b", "c"} s2 := []string{"d", "e", "f"} collect.Contains([][]string{s1, s2}, s2) // true
-
Diff
computes the difference set of two slicesExamples
d := []int{1, 2, 3} collect.Diff(d, []int{2, 3}) // []int{1}
-
Filter
filters the elements in the sliceExamples
collect.Filter([]int{1, 2, 3, 4, 5}, func(value, index int) bool { return value % 2 == 0 }) // []int{2, 4}
-
Map
iterates over and sets the value of the elements in the sliceExamples
collect.Map([]int{1, 2, 3}, func(value, index int) int { return value * 2 }) // []int{2, 4, 6}
-
Unique
removes duplicate elements in the sliceExamples
d := []int{1, 2, 3, 3, 4} collect.Unique(d) // []int{1, 2, 3, 4}
-
Duplicates
gets the duplicate elements in the sliceExamples
d := []string{"a", "b", "a", "c"} collect.Duplicates(d) // map[int]string{2: "a"}
-
Merge
merges the current slice with other slicesExamples
d1 := []int{1, 2} d2 := []int{3, 4} d3 := []int{5, 6} collect.Merge(d1, d2) // []int{1, 2, 3, 4} collect.Merge(d1, d2, d3) // []int{1, 2, 3, 4, 5, 6}
-
Random
gets an element of the slice at randomExamples
d := []int{1, 2} value, ok := collect.Random(d) // 1 or 2, true d := []int{} value, ok := collect.Random(d) // 0, false
-
Reverse
reverses the elements in a sliceExamples
d := []int{1, 2} collect.Reverse(d) // []int{2, 1}
-
Shuffle
randomly shuffles the elements in a sliceExamples
d := []int{1, 2} collect.Shuffle(d) // []int{1, 2} or []int{2, 1}
-
Slice
takes a segment from a sliceExamples
Function signature:
Slice(items T, offset int)
d := []int{1, 2, 3, 4, 5} collect.Slice(d, 2) // []int{3, 4, 5} collect.Slice(d, -1) // []int{5} collect.Slice(d, -2) // []int{4, 5}
Function signature:
Slice(items T, offset, length int)
d := []int{1, 2, 3, 4, 5} collect.Slice(d, 0, 2) // []int{1, 2} collect.Slice(d, 2, 3) // []int{3, 4, 5} collect.Slice(d, 3, -2) // []int{3, 4} collect.Slice(d, -4, 3) // []int{2, 3, 4}
-
Split
splits a slice into multiple slices by the specified amountExamples
d := []int{1, 2, 3, 4, 5} collect.Split(d, 2) // [][]int{{1, 2}, {3, 4}, {5}}
-
Splice
removes a segment from the sliceExamples
Function signature:
Splice(items T, offset int)
d := []int{1, 2, 3, 4, 5} collect.Splice(&d, 2) // []int{3, 4, 5} d // []int{1, 2}
Function signature:
Splice(items T, offset, length int)
d := []int{1, 2, 3, 4, 5} collect.Splice(&d, 2, 2) // []int{3, 4} d // []int{1, 2, 5}
Function signature:
Splice(items T, offset, length int, replacements ...T|E)
d1 := []int{1, 2, 3, 4} collect.Splice(&d1, 1, 2, []int{22, 33}) // []int{2, 3} d1 // []int{1, 22, 33, 4} d2 := []int{1, 2, 3, 4} collect.Splice(&d2, 1, 2, 22, 33) // []int{2, 3} d2 // []int{1, 22, 33, 4} d3 := []int{1, 2, 3, 4} collect.Splice(&d3, 1, 2, []int{22}, 33, []int{55}) // []int{2, 3} d3 // []int{1, 22, 33, 55, 4}
It is worth noting that this method also supports the use of negative numbers as arguments, and its behavior is the same as that of
Slice
, which is not repeated here due to space constraints. -
Reduce
reduces the collection to a single value, and the parameters of each iteration are the results of the previous iterationExamples
collect.Reduce([]int{1, 2, 3}, 100, func(carry, value, key int) int { return carry + value }) // 106
-
Pop
removes and returns the last element of the collectionExamples
d := []int{1, 2} v, ok := collect.Pop(&d) // 2, true d // []int{1} c := collect.UseSlice([]int{1, 2}) v, ok := c.Pop() // 2, true c.All() // []int{1}
-
Push
appends an element to the end of a collectionExamples
d := []int{1, 2} Push(&d, 3) d // []int{1, 2, 3} collect.UseSlice([]int{1, 2}).Push(3).All() // []int{1, 2, 3}
-
Where
filters the collection by the specified rulesExamples
Function signature:
Where(items T, target any)
collect.Where([]int{1, 2, 3}, 2) // []int{2}
Function signature:
Where(items T, operator string, target any)
d := []int{1, 2, 3, 4} collect.Where(d, "=", 2) // []int{2} collect.Where(d, "!=", 2) // []int{1, 3, 4} collect.Where(d, ">", 2) // []int{3, 4} collect.Where(d, ">=", 2) // []int{2, 3, 4} collect.Where(d, "<", 3) // []int{1, 2} collect.Where(d, "<=", 3) // []int{1, 2, 3}
Function signature:
Where(items T, key any, target any)
d := []User{{ID: 1, Name: "Hugo"}, {ID: 2, Name: "Lisa"}, {ID: 3, Name: "Iris"}, {ID: 4, Name: "Lisa"}} collect.Where(d, "Name", "Lisa") // []User{{2 Lisa} {4 Lisa}}
Function signature:
Where(items T, key any, operator string, target any)
d := []User{{ID: 1, Name: "Hugo"}, {ID: 2, Name: "Lisa"}, {ID: 3, Name: "Iris"}, {ID: 4, Name: "Lisa"}} collect.Where(d, "Name", "!=", "Lisa") // []User{{1 Hugo} {3 Iris}}
-
WhereIn
removes elements from the collection that do not exist in the specified sliceExamples
Function signature:
WhereIn(items T, targets []any)
d := []int{1, 2, 3, 4} collect.WhereIn(d, []int{2, 3}) // []int{2, 3}
Function signature:
WhereIn(items T, key any, targets []any)
d := []User{{ID: 1, Name: "Hugo"}, {ID: 2, Name: "Lisa"}, {ID: 3, Name: "Iris"}, {ID: 4, Name: "Lisa"}} collect.WhereIn(d, "Name", []string{"Hugo", "Iris"}) // []User{{1 Hugo} {3 Iris}}
-
WhereNotIn
removes elements from the collection that exist in the specified sliceExamples
Function signature:
WhereNotIn(items T, targets []any)
d := []int{1, 2, 3, 4} collect.WhereNotIn(d, []int{2, 3}) // []int{1, 4}
Function signature:
WhereNotIn(items T, key any, targets []any)
d := []User{{ID: 1, Name: "Hugo"}, {ID: 2, Name: "Lisa"}, {ID: 3, Name: "Iris"}, {ID: 4, Name: "Lisa"}} collect.WhereNotIn(d, "Name", []string{"Lisa", "Iris"}) // []User{{1 Hugo}}
Exactly the same as slice, you just pass in the array converted to a slice:
arr := [3]int{1, 2, 3}
collect.Len(arr[:])
// or
collect.UseSlice(arr[:]).Len()
The corresponding chained function is collect.UseMap()
-
Len
gets the number of elements in the mapExamples
d1 := map[string]int{"a": 1, "b": 2, "c": 3} collect.Len(d1) // 3
-
Empty
checks if the map is emptyExamples
var d map[string]int collect.Empty(d) // true
-
Only
gets the elements of the map with the specified keysExamples
d := map[string]int{"a": 1, "b": 2, "c": 3} collect.Only(d, "a") // map[string]int{"a": 1} collect.Only(d, "a", "b") // map[string]int{"a": 1, "b": 2}
-
Except
gets the elements of the map with the specified keys removedExamples
d := map[string]int{"a": 1, "b": 2, "c": 3} collect.Except(d, "a") // map[string]int{"b": 2, "c": 3} collect.Except(d, "a", "b") // map[string]int{"c": 3}
-
Keys
gets all the keys in the mapExamples
d := map[string]int{"a": 1, "b": 2, "c": 3} collect.Keys(d) // []string{"a", "b", "c"}
-
DiffKeys
compares with the given collection and returns the key/value pairs in the given collection that do not exist in the original collectionExamples
d1 := map[string]int{"a": 1, "b": 2, "c": 3} d2 := map[string]int{"b": 22, "c": 33} collect.DiffKeys(d1, d2) // map[string]int{"a": 1}
-
Has
checks if the map contains the specified keyExamples
d := map[string]int{"a": 1} collect.Has(d, "a") // true
-
Get
gets the value of the specified key in the mapExamples
d := map[string]int{"a": 1} value, ok := collect.Get(d, "a") // 1, true value, ok := collect.Get(d, "b") // 0, false
-
Put
sets the value of the specified key in the mapExamples
d := map[string]int{"a": 1} collect.Put(d, "b", 2) // map[string]int{"a": 1, "b": 2}
-
Pull
removes the specified key from the collection and returns its valueExamples
d := map[string]int{"a": 1, "b": 2} v, ok := collect.Pull(d, "b") // 2, true d // map[string]int{"a": 1}
-
Merge
merges the current map with other mapsExamples
d1 := map[string]int{"a": 1, "b": 2} d2 := map[string]int{"b": 22} d3 := map[string]int{"b": 222, "c": 3} collect.MapMerge(d1, d2) // map[string]int{"a": 1, "b": 22} collect.UseMap(d1).Merge(d2).All() // Equal to the above collect.MapMerge(d1, d2, d3) // map[string]int{"a": 1, "b": 222, "c": 3} collect.UseMap(d1).Merge(d2, d3).All() // Equal to the above
-
Union
unites the current map with other maps, and the items in the original map are given priorityExamples
d1 := map[string]int{"a": 1, "b": 2} d2 := map[string]int{"b": 22, "c": 3} collect.Union(d1, d2) // map[string]int{"a": 1, "b": 2, "c": 3}
The corresponding chained function is collect.UseNumber()
,which is a subset of slice and includes, in addition to all the methods of slice, the additional:
-
Sum
calculates the sumExamples
collect.Sum([]float64{1, 3.14}) // 4.14
-
Min
calculates the minimum valueExamples
collect.Min([]int{0, 1, -3}) // -3
-
Max
calculates the maximum valueExamples
collect.Max([]int{0, 1, -3}) // 1
-
Sort
sorts the numbers in the collection in ascending orderExamples
collect.Sort([]float64{1, -4, 0, -4.3}) // []float64{-4.3, -4, 0, 1}
-
SortDesc
sorts the numbers in the collection in descending orderExamples
collect.SortDesc([]float64{1, -4, 0, -4.3}) // []float64{1, 0, -4, -4.3}
-
Avg
calculates the averageExamples
collect.Avg([]int{1, 2, 3, 4}) // 2.5
-
Median
calculates the medianExamples
collect.Median([]int{1, 2, 3, 4}) // 2.5
Due to Golang's support for generics, it is not possible to define generic types in methods, so only their function implementations (which do not support chain calls) are listed below:
-
AnyGet
gets value of arbitrary types (slices, maps, arrays, structures, and pointers to these) in a non-strict formExamples
m := map[string]int{"a": 1, "b": 2} collect.AnyGet[int](m, "b") // 2 u := &User{"Email": "user@example.com"} collect.AnyGet[string](u, "Email") // user@example.com s := [][]int{{1, 2}, {3, 4}} collect.AnyGet[[]int](s, 1) // []{3, 4}
-
Pluck
retrieves all values for a given key. supports all values supported byAnyGet
Examples
d := []User{{ID: 33, Name: "Lucy"}, {ID: 193, Name: "Peter"}} collect.Pluck[int](d, "ID") // int[]{33, 193}
-
MapPluck
retrieves all values of a given key, only maps are supportedExamples
d := []map[string]int{{"ID": 33, "Score": 10}, {"ID": 193, "Score": 6}} collect.MapPluck(d, "ID") // int[]{33, 193}
-
KeyBy
retrieves a collection with the value of the given key as the identifier (if there are duplicate keys, only the last one will be kept). Supports all values supported byAnyGet
Examples
d := []User{{ID: 33, Name: "Lucy"}, {ID: 193, Name: "Peter"}, {ID: 194, Name: "Peter"}} collect.KeyBy[string](d, "Name") // map[Lucy:{33 Lucy} Peter:{194 Peter}]
-
MapKeyBy
retrieves the collection with the value of the given key as the identifier (if there are duplicate keys, only the last one will be kept), only maps are supportedExamples
d := []map[string]int{{"ID": 33, "Score": 6}, {"ID": 193, "Score": 10}, {"ID": 194, "Score": 10}} collect.MapKeyBy(d, "Score") // map[6:map[ID:33 Score:6] 10:map[ID:194 Score:10]]
-
GroupBy
groups the items in a collection using the value of the given key as the identifier. Supports all values supported byAnyGet
Examples
d := []User{{ID: 33, Name: "Lucy"}, {ID: 193, Name: "Peter"}, {ID: 194, Name: "Peter"}} collect.GroupBy[string](d, "Name") // map[Lucy:[{33 Lucy}] Peter:[{193 Peter} {194 Peter}]]
-
MapGroupBy
groups items in a collection using the value of the given key as the identifier, only maps are supportedExamples
d := []map[string]int{{"ID": 33, "Score": 6}, {"ID": 193, "Score": 10}, {"ID": 194, "Score": 10}} collect.MapGroupBy(d, "Score") // map[6:[map[ID:33 Score:6]] 10:[map[ID:193 Score:10] map[ID:194 Score:10]]]
-
Count
counts the number of occurrences of each element in the sliceExamples
d := []bool{true, true, false} collect.Count(d) // map[bool]int{true: 2, false: 1}
-
Times
creates a new collection of slice by calling the callback with specified number of timesExamples
collect.Times(3, func(number int) float64 { return float64(number) * 3.14 }) // *SliceCollection{[]float64{3.14, 6.28, 9.42}}
-
SortBy
calls a callback for each element and performs an ascending sort by the return value of the callbackExamples
collect.SortBy([]int{2, 1, 3}, func(item, index int) string { return strconv.Itoa(item) }) // *SliceCollection{[]int{1, 2, 3}}
-
SortByDesc
calls a callback for each element and performs a descending sort by the return value of the callbackExamples
collect.SortByDesc([]int{2, 1, 3}, func(item, index int) string { return strconv.Itoa(item) }) // *SliceCollection{[]int{3, 2, 1}}
go-collection is MIT licensed.