go-collection
English | 简体中文
go-collection
provides developers with a convenient set of functions for working with common slices, dicts, and arrays of 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).All()
Installation
go get -u github.com/sxyazi/go-collection
Then import it
import collect "github.com/sxyazi/go-collection"
API
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.
Slice
The corresponding chained function is collect.UseSlice()
-
Len: Gets the length of the slice
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 slice
d := []float64{1, 2, 3} collect.Each(d, func(value float64, index int) { fmt.Println(index, value) })
-
Empty: Checks if the slice is empty
var d []int collect.Empty(d) // true
-
Same: Checks if the contents of two slices are the same
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 slice
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 slice
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.
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 element
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 slices
d := []int{1, 2, 3} collect.Diff(d, []int{2, 3}) // []int{1}
-
Filter: Filters the elements in the slice
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 slice
collect.Map([]int{1, 2, 3}, func(value, index int) int { return value * 2 }) // []int{2, 4, 6}
-
Unique: Removes duplicate elements from slices
d := []int{1, 2, 3, 3, 4} collect.Unique(d) // []int{1, 2, 3, 4}
-
Merge: Merges the current slice with other slices
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 random
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 slice
d := []int{1, 2} collect.Reverse(d) // []int{2, 1}
-
Shuffle: Randomly shuffles the elements in a slice
d := []int{1, 2} collect.Shuffle(d) // []int{1, 2} or []int{2, 1}
-
Slice: Takes a segment from a slice
Function signature:
Slice(items T, offset int)
d := []int{1, 2, 3, 4} collect.Slice(d, 2) // []int{3, 4}
Function signature:
Slice(items T, offset, length int)
collect.Slice(d, 0, 2) // []int{1, 2} collect.Slice(d, 2, 2) // []int{3, 4}
-
Split: Splits a slice into multiple slices by the specified amount
d := []int{1, 2, 3, 4, 5} collect.Split(d, 2) // [][]int{{1, 2}, {3, 4}, {5}}
-
Splice: Removes a segment from the slice
Function signature:
Splice(items T, offset int)
d := []int{1, 2, 3, 4, 5} collect.Splice(d, 2) // []int{1, 2}
Function signature:
Splice(items T, offset, length int)
d := []int{1, 2, 3, 4, 5} collect.Splice(d, 2, 2) // []int{1, 2, 5}
Function signature:
Slice(items T, offset, length int, replacements ...T|E)
d := []int{1, 2, 3, 4} collect.Splice(d, 1, 2, []int{22, 33}) // []int{1, 22, 33, 4} collect.Splice(d, 1, 2, 233, 333) // []int{1, 222, 333, 4} collect.Splice(d, 1, 2, []int{22}, 33, []int{44}) // []int{1, 22, 33, 44, 4}
-
Count: Counts the number of occurrences of each element in the slice
d := []bool{true, true, false} collect.Count(d) // map[bool]int{true: 2, false: 1}
Array
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()
Dict
The corresponding chained function is collect.UseMap()
-
Only: Gets the elements of the dict with the specified keys
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 dict with the specified keys removed
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 dict
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 collection
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 dict contains the specified key
d := map[string]int{"a": 1} collect.Has(d, "a") // true
-
Set: Sets the value of the specified key in the dict
d := map[string]int{"a": 1} collect.Set(d, "b", 2) // map[string]int{"a": 1, "b": 2}
-
Get: Gets the value of the specified key in the dict
d := map[string]int{"a": 1} value, ok := collect.Get(d, "a") // 1, true value, ok := collect.Get(d, "b") // 0, false
-
Merge: Merges the current dict with other dicts
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 dict with other dicts, and the items in the original dict are given priority
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}
Number slice
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 sum
collect.Sum([]float64{1.1, 2.2, 3.3}) // 6.6
-
Avg: Calculates the average
collect.Avg([]float64{1.1, 2.2, 3.3}) // 2.2
-
Min: Calculates the minimum value
collect.Min([]int{0, 1, -3}) // -3
-
Max: Calculates the maximum value
collect.Max([]int{0, 1, -3}) // 1
Standalone functions
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, dicts, arrays, structures, and pointers to these) in a non-strict form
m := map[string]int{"a": 1, "b": 2} collect.AnyGet[int](m, "b") // 2 u := &User{"Email": "[email protected]"} collect.AnyGet[string](u, "Email") // [email protected] s := [][]int{{1, 2}, {3, 4}} collect.AnyGet[[]int](s, 1) // []{3, 4}
-
Pluck: Retrieves all values for a given key and supports all values supported by
AnyGet
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 dicts are supported
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 by
AnyGet
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 set with the value of the given key as the identifier (if there are duplicate keys, only the last one will be kept), only dicts are supported
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 by
AnyGet
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 dicts are supported
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]]]