Documentation
¶
Overview ¶
Package gmap provides generic operations for maps.
💡 HINT: We provide similar functionality for different types in different packages. For example, github.com/bytedance/gg/gslice.Clone for copying slice while Clone for copying map.
- Use github.com/bytedance/gg/gslice for slice operations.
- Use github.com/bytedance/gg/gvalue for value operations.
- Use github.com/bytedance/gg/gptr for pointer operations.
- …
Operations ¶
Keys / Values getter:
High-order functions:
CRUD operations:
Partition operations:
Math operations:
Set operations:
Type casting/assertion/conversion:
Predicates:
Interface type satisfies comparable constraint after Go1.20 and later ¶
According Go1.20 Language Change, Comparable types (such as ordinary interfaces) may now satisfy comparable constraints, even if the type arguments are not strictly comparable (comparison may PANIC at runtime).
Which means operations of gmap can be used on more map types, for example:
var m map[io.Reader]string readers = gmap.Keys (m) // Go1.19 and earlier: ❌ io.Reader does not implement comparable // Go1.20 and later: ✔️ running well
It also means gmap operations may PANIC at runtime:
// Implement io.Reader for unhashable.
type unhashable []int
func (unhashable) Read([]byte) (_ int, _ error) { return }
m := make(map[io.Reader]string)
key := io.Reader(unhashable{})
_, _ = gmap.LoadOrStore(m, key, "")
// Go1.19 and earlier: ❌ io.Reader does not implement comparable
// Go1.20 and later: ❌ panic: runtime error: hash of unhashable type main.unhashable
Conflict resolution ¶
When operating on multiple maps, key conflicts often occur, the newer value replace the old by default (DiscardOld). These operations include but are not limited to Invert, Union, Intersect and so on…
We provide ConflictFunc to help user to customize conflict resolution. All of above operations supports variant with ConflictFunc support:
Example ¶
// Keys / Values getter
fmt.Println(Keys(map[int]int{1: 2})) // [1]
fmt.Println(Values(map[int]int{1: 2})) // [2]
fmt.Println(Items(map[int]int{1: 2}).Unzip()) // [1] [2]
fmt.Println(OrderedKeys(map[int]int{1: 2, 2: 3, 3: 4})) // [1, 2, 3]
fmt.Println(OrderedValues(map[int]int{1: 2, 2: 3, 3: 4})) // [2, 3, 4]
fmt.Println(OrderedItems(map[int]int{1: 2, 2: 3, 3: 4}).Unzip()) // [1, 2, 3] [2, 3, 4]
f := func(k, v int) string { return strconv.Itoa(k) + ":" + strconv.Itoa(v) }
fmt.Println(ToSlice(map[int]int{1: 2}, f)) // ["1:2"]
fmt.Println(ToOrderedSlice(map[int]int{1: 2, 2: 3, 3: 4}, f)) // ["1:2", "2:3", "3:4"]
// High-order function
fmt.Println(gson.ToString(Map(map[int]int{1: 2, 2: 3, 3: 4}, func(k int, v int) (string, string) {
return strconv.Itoa(k), strconv.Itoa(k + 1)
}))) // {"1":"2", "2":"3", "3":"4"}
fmt.Println(gson.ToString(Filter(map[int]int{1: 2, 2: 3, 3: 4}, func(k int, v int) bool {
return k+v > 3
}))) // {"2":2, "3":3}
// CRUD operation
fmt.Println(Contains(map[int]int{1: 2, 2: 3, 3: 4}, 1)) // true
fmt.Println(ContainsAny(map[int]int{1: 2, 2: 3, 3: 4}, 1, 4)) // true
fmt.Println(ContainsAll(map[int]int{1: 2, 2: 3, 3: 4}, 1, 4)) // false
fmt.Println(Load(map[int]int{1: 2, 2: 3, 3: 4}, 1).Value()) // 2
fmt.Println(LoadAny(map[int]int{1: 2, 2: 3, 3: 4}, 1, 4).Value()) // 2
fmt.Println(LoadAll(map[int]int{1: 2, 2: 3, 3: 4}, 1, 4)) // []
fmt.Println(LoadSome(map[int]int{1: 2, 2: 3, 3: 4}, 1, 4)) // [2]
// Partion operation
Chunk(map[int]int{1: 2, 2: 3, 3: 4, 4: 5, 5: 6}, 2) // possible output: [{1:2, 2:3}, {3:4, 4:5}, {5:6}]
Divide(map[int]int{1: 2, 2: 3, 3: 4, 4: 5, 5: 6}, 2) // possible output: [{1:2, 2:3, 3:4}, {4:5, 5:6}]
// Math operation
fmt.Println(Max(map[int]int{1: 2, 2: 3, 3: 4}).Value()) // 4
fmt.Println(Min(map[int]int{1: 2, 2: 3, 3: 4}).Value()) // 2
fmt.Println(MinMax(map[int]int{1: 2, 2: 3, 3: 4}).Value().Values()) // 2 4
fmt.Println(Sum(map[int]int{1: 2, 2: 3, 3: 4})) // 9
// Set operation
fmt.Println(gson.ToString(Union(map[int]int{1: 2, 2: 3, 3: 4}, map[int]int{3: 14, 4: 15, 5: 16}))) // {1:2, 2:3, 3:14, 4:15, 5:16}
fmt.Println(gson.ToString(Intersect(map[int]int{1: 2, 2: 3, 3: 4}, map[int]int{3: 14, 4: 15, 5: 16}))) // {3:14}
fmt.Println(gson.ToString(Diff(map[int]int{1: 2, 2: 3, 3: 4}, map[int]int{3: 14, 4: 15, 5: 16}))) // {1:2, 2:3}
fmt.Println(gson.ToString(UnionBy(gslice.Of(map[int]int{1: 2, 2: 3, 3: 4}, map[int]int{3: 14, 4: 15, 5: 16}), DiscardNew[int, int]()))) // {1:2, 2:3, 3:4, 4:15, 5:16}
fmt.Println(gson.ToString(IntersectBy(gslice.Of(map[int]int{1: 2, 2: 3, 3: 4}, map[int]int{3: 14, 4: 15, 5: 16}), DiscardNew[int, int]()))) // {3:4}
Output: [1] [2] [1] [2] [1 2 3] [2 3 4] [1 2 3] [2 3 4] [1:2] [1:2 2:3 3:4] {"1":"2","2":"3","3":"4"} {"2":3,"3":4} true true false 2 2 [] [2] 4 2 2 4 9 {"1":2,"2":3,"3":14,"4":15,"5":16} {"3":14} {"1":2,"2":3} {"1":2,"2":3,"3":4,"4":15,"5":16} {"3":4}
Index ¶
- func Avg[K comparable, V constraints.Number](m map[K]V) float64
- func AvgBy[K comparable, V any, N constraints.Number](m map[K]V, f func(V) N) float64
- func Chunk[M ~map[K]V, K comparable, V any](m M, size int) []M
- func Clone[M ~map[K]V, K comparable, V any](m M) M
- func CloneBy[M ~map[K]V, K comparable, V any](m M, f func(V) V) M
- func Compact[M ~map[K]V, K, V comparable](m M) M
- func Contains[K comparable, V any](m map[K]V, k K) bool
- func ContainsAll[K comparable, V any](m map[K]V, ks ...K) bool
- func ContainsAny[K comparable, V any](m map[K]V, ks ...K) bool
- func Count[K, V comparable](m map[K]V, v V) int
- func CountBy[K comparable, V any](m map[K]V, f func(K, V) bool) int
- func CountValueBy[K comparable, V any](m map[K]V, f func(V) bool) int
- func Diff[M ~map[K]V, K comparable, V any](m M, againsts ...M) M
- func Divide[M ~map[K]V, K comparable, V any](m M, n int) []M
- func Equal[K, V comparable](m1, m2 map[K]V) bool
- func EqualBy[K comparable, V any](m1, m2 map[K]V, eq func(v1, v2 V) bool) bool
- func Filter[M ~map[K]V, K comparable, V any](m M, f func(K, V) bool) M
- func FilterByKeys[M ~map[K]V, K comparable, V any](m M, keys ...K) M
- func FilterByValues[M ~map[K]V, K, V comparable](m M, values ...V) M
- func FilterKeys[M ~map[K]V, K comparable, V any](m M, f func(K) bool) M
- func FilterMap[K1, K2 comparable, V1, V2 any](m map[K1]V1, f func(K1, V1) (K2, V2, bool)) map[K2]V2
- func FilterMapKeys[K1, K2 comparable, V any](m map[K1]V, f func(K1) (K2, bool)) map[K2]V
- func FilterMapValues[K comparable, V1, V2 any](m map[K]V1, f func(V1) (V2, bool)) map[K]V2
- func FilterValues[M ~map[K]V, K comparable, V any](m M, f func(V) bool) M
- func Indirect[K comparable, V any](m map[K]*V) map[K]V
- func IndirectOr[K comparable, V any](m map[K]*V, fallback V) map[K]V
- func Intersect[M ~map[K]V, K comparable, V any](ms ...M) M
- func IntersectBy[M ~map[K]V, K comparable, V any](ms []M, onConflict ConflictFunc[K, V]) M
- func Invert[K, V comparable](m map[K]V) map[V]K
- func InvertBy[K, V comparable](m map[K]V, onConflict ConflictFunc[V, K]) map[V]K
- func InvertGroup[K, V comparable](m map[K]V) map[V][]K
- func Items[K comparable, V any](m map[K]V) tuple.S2[K, V]
- func Keys[K comparable, V any](m map[K]V) []K
- func Len[K comparable, V any](m map[K]V) int
- func Load[K comparable, V any](m map[K]V, k K) goption.O[V]
- func LoadAll[K comparable, V any](m map[K]V, ks ...K) []V
- func LoadAndDelete[K comparable, V any](m map[K]V, k K) goption.O[V]
- func LoadAny[K comparable, V any](m map[K]V, ks ...K) (r goption.O[V])
- func LoadBy[K comparable, V any](m map[K]V, f func(K, V) bool) goption.O[V]
- func LoadItemBy[K comparable, V any](m map[K]V, f func(K, V) bool) goption.O[tuple.T2[K, V]]
- func LoadKey[K, V comparable](m map[K]V, v V) goption.O[K]
- func LoadKeyBy[K comparable, V any](m map[K]V, f func(K, V) bool) goption.O[K]
- func LoadOrStore[K comparable, V any](m map[K]V, k K, defaultV V) (v V, loaded bool)
- func LoadOrStoreLazy[K comparable, V any](m map[K]V, k K, f func() V) (v V, loaded bool)
- func LoadSome[K comparable, V any](m map[K]V, ks ...K) []V
- func Map[K1, K2 comparable, V1, V2 any](m map[K1]V1, f func(K1, V1) (K2, V2)) map[K2]V2
- func MapKeys[K1, K2 comparable, V any](m map[K1]V, f func(K1) K2) map[K2]V
- func MapValues[K comparable, V1, V2 any](m map[K]V1, f func(V1) V2) map[K]V2
- func Max[K comparable, V constraints.Ordered](m map[K]V) goption.O[V]
- func MaxBy[K comparable, V any](m map[K]V, less func(V, V) bool) goption.O[V]
- func Merge[M ~map[K]V, K comparable, V any](ms ...M) M
- func Min[K comparable, V constraints.Ordered](m map[K]V) goption.O[V]
- func MinBy[K comparable, V any](m map[K]V, less func(V, V) bool) goption.O[V]
- func MinMax[K comparable, V constraints.Ordered](m map[K]V) goption.O[tuple.T2[V, V]]
- func MinMaxBy[K comparable, V any](m map[K]V, less func(V, V) bool) goption.O[tuple.T2[V, V]]
- func OrderedItems[K constraints.Ordered, V any](m map[K]V) tuple.S2[K, V]
- func OrderedKeys[K constraints.Ordered, V any](m map[K]V) []K
- func OrderedValues[K constraints.Ordered, V any](m map[K]V) []V
- func Peek[K comparable, V any](m map[K]V) goption.O[V]
- func PeekItem[K comparable, V any](m map[K]V) goption.O[tuple.T2[K, V]]
- func Pop[K comparable, V any](m map[K]V) goption.O[V]
- func PopItem[K comparable, V any](m map[K]V) goption.O[tuple.T2[K, V]]
- func PtrOf[K comparable, V any](m map[K]V) map[K]*V
- func Reject[M ~map[K]V, K comparable, V any](m M, f func(K, V) bool) M
- func RejectByKeys[M ~map[K]V, K comparable, V any](m M, keys ...K) M
- func RejectByValues[M ~map[K]V, K, V comparable](m M, values ...V) M
- func RejectKeys[M ~map[K]V, K comparable, V any](m M, f func(K) bool) M
- func RejectValues[M ~map[K]V, K comparable, V any](m M, f func(V) bool) M
- func Sum[K comparable, V constraints.Number](m map[K]V) V
- func SumBy[K comparable, V any, N constraints.Number](m map[K]V, f func(V) N) N
- func ToOrderedSlice[K constraints.Ordered, V, T any](m map[K]V, f func(K, V) T) []T
- func ToSlice[K comparable, V, T any](m map[K]V, f func(K, V) T) []T
- func TryFilterMap[K1, K2 comparable, V1, V2 any](m map[K1]V1, f func(K1, V1) (K2, V2, error)) map[K2]V2
- func TryFilterMapKeys[K1, K2 comparable, V any](m map[K1]V, f func(K1) (K2, error)) map[K2]V
- func TryFilterMapValues[K comparable, V1, V2 any](m map[K]V1, f func(V1) (V2, error)) map[K]V2
- func TryMap[K1, K2 comparable, V1, V2 any](m map[K1]V1, f func(K1, V1) (K2, V2, error)) gresult.R[map[K2]V2]
- func TryMapKeys[K1, K2 comparable, V any](m map[K1]V, f func(K1) (K2, error)) gresult.R[map[K2]V]
- func TryMapValues[K comparable, V1, V2 any](m map[K]V1, f func(V1) (V2, error)) gresult.R[map[K]V2]
- func TypeAssert[To any, K comparable, From any](m map[K]From) map[K]To
- func Union[M ~map[K]V, K comparable, V any](ms ...M) M
- func UnionBy[M ~map[K]V, K comparable, V any](ms []M, onConflict ConflictFunc[K, V]) M
- func Values[K comparable, V any](m map[K]V) []V
- type ConflictFunc
- func DiscardNew[K comparable, V any]() ConflictFunc[K, V]
- func DiscardNil[K comparable, V comparable](fallback ConflictFunc[K, *V]) ConflictFunc[K, *V]
- func DiscardOld[K comparable, V any]() ConflictFunc[K, V]
- func DiscardZero[K comparable, V comparable](fallback ConflictFunc[K, V]) ConflictFunc[K, V]
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Avg ¶
func Avg[K comparable, V constraints.Number](m map[K]V) float64
Avg returns the arithmetic mean of the values of map s.
🚀 EXAMPLE:
Avg(map[string]int{"1": 1, "2": 2, "3": 3}) ⏩ 2.0
💡 AKA: Mean, Average
func AvgBy ¶
func AvgBy[K comparable, V any, N constraints.Number](m map[K]V, f func(V) N) float64
AvgBy applies function f to each values of map m, returns the arithmetic mean of function result.
💡 AKA: MeanBy, AverageBy
func Chunk ¶
func Chunk[M ~map[K]V, K comparable, V any](m M, size int) []M
Chunk splits map into length-n chunks and returns chunks by a new slice.
The last chunk will be shorter if n does not evenly divide the length of the map.
⚠️ WARNING: The values in chunks will be in an indeterminate order.
func Clone ¶
func Clone[M ~map[K]V, K comparable, V any](m M) M
Clone returns a shallow copy of map. If the given map is nil, nil is returned.
🚀 EXAMPLE:
Clone(map[int]int{1: 1, 2: 2}) ⏩ map[int]int{1: 1, 2: 2}
Clone(map[int]int{}) ⏩ map[int]int{}
Clone[int, int](nil) ⏩ nil
💡 HINT: Both keys and values are copied using assignment (=), so this is a shallow clone. If you want to do a deep clone, use CloneBy with an appropriate value clone function.
💡 AKA: Copy
func CloneBy ¶
func CloneBy[M ~map[K]V, K comparable, V any](m M, f func(V) V) M
CloneBy is variant of Clone, it returns a copy of the map. Elements are copied using function f. If the given map is nil, nil is returned.
TODO: Example
💡 AKA: CopyBy
func Compact ¶
func Compact[M ~map[K]V, K, V comparable](m M) M
Compact removes all zero values from given map m, returns a new map.
🚀 EXAMPLE:
m := map[int]string{0: "", 1: "foo", 2: "", 3: "bar"}
Compact(m) ⏩ map[int]string{1: "foo", 3: "bar"}
💡 HINT: See github.com/bytedance/gg/gvalue.Zero for details of zero value.
func Contains ¶
func Contains[K comparable, V any](m map[K]V, k K) bool
Contains returns whether the key occur in map.
🚀 EXAMPLE:
m := map[int]string{1: ""}
Contains(m, 1) ⏩ true
Contains(m, 0) ⏩ false
var nilMap map[int]string
Contains(nilMap, 0) ⏩ false
💡 HINT: See also ContainsAll, ContainsAny if you have multiple values to query.
func ContainsAll ¶
func ContainsAll[K comparable, V any](m map[K]V, ks ...K) bool
ContainsAll returns whether all of given keys occur in map.
🚀 EXAMPLE:
m := map[int]string{1: "", 2: "",}
ContainsAll(m, 1, 2) ⏩ true
ContainsAll(m, 1, 3) ⏩ false
ContainsAll(m, 3) ⏩ false
func ContainsAny ¶
func ContainsAny[K comparable, V any](m map[K]V, ks ...K) bool
ContainsAny returns whether any of given keys occur in map.
🚀 EXAMPLE:
m := map[int]string{1: "", 2: ""}
ContainsAny(m, 1, 2) ⏩ true
ContainsAny(m, 1, 3) ⏩ true
ContainsAny(m, 3) ⏩ false
func Count ¶
func Count[K, V comparable](m map[K]V, v V) int
Count returns the times of value v that occur in map m.
🚀 EXAMPLE:
Count(map[int]string{1: "a", 2: "a", 3: "b"}, "a") ⏩ 2
💡 HINT:
- Use CountValueBy if type of v is non-comparable
- Use CountBy if you need to consider key when counting
func CountBy ¶
func CountBy[K comparable, V any](m map[K]V, f func(K, V) bool) int
CountBy returns the times of pair (k, v) in map m that satisfy the predicate f.
🚀 EXAMPLE:
f := func (k int, v string) bool {
i, _ := strconv.Atoi(v)
return k%2 == 1 && i%2 == 1
}
CountBy(map[int]string{1: "1", 2: "2", 3: "3"}, f) ⏩ 0
CountBy(map[int]string{1: "1", 2: "2", 3: "4"}, f) ⏩ 1
func CountValueBy ¶
func CountValueBy[K comparable, V any](m map[K]V, f func(V) bool) int
CountValueBy returns the times of value v in map m that satisfy the predicate f.
🚀 EXAMPLE:
f := func (v string) bool {
i, _ := strconv.Atoi(v)
return i%2 == 1
}
CountValueBy(map[int]string{1: "1", 2: "2", 3: "3"}, f) ⏩ 2
CountValueBy(map[int]string{1: "1", 2: "2", 3: "4"}, f) ⏩ 1
func Diff ¶
func Diff[M ~map[K]V, K comparable, V any](m M, againsts ...M) M
Diff returns the difference of map m against other maps as a new map.
💡 NOTE: If the result is an empty set, always return an empty map instead of nil
🚀 EXAMPLE:
m := map[int]int{1: 1, 2: 2}
Diff(m, nil) ⏩ map[int]int{1: 1, 2: 2}
Diff(m, map[int]{1: 1}) ⏩ map[int]int{2: 2}
Diff(m, map[int]{3: 3}) ⏩ map[int]int{1: 1, 2: 2}
💡 HINT: Use github.com/bytedance/gg/collection/set.Set if you need a set data structure
TODO: Value type of againsts can be diff from m.
func Divide ¶
func Divide[M ~map[K]V, K comparable, V any](m M, n int) []M
Divide splits map into exactly n slices and returns chunks by a new slice.
The length of chunks will be different if n does not evenly divide the length of the slice.
⚠️ WARNING: The values in chunks will be in an indeterminate order.
func Equal ¶
func Equal[K, V comparable](m1, m2 map[K]V) bool
Equal reports whether two maps contain the same key/value pairs. values are compared using ==.
🚀 EXAMPLE:
Equal(map[int]int{1: 1, 2: 2}, map[int]int{1: 1, 2: 2}) ⏩ true
Equal(map[int]int{1: 1}, map[int]int{1: 1, 2: 2}) ⏩ false
Equal(map[int]int{}, map[int]int{}) ⏩ true
Equal(map[int]int{}, nil) ⏩ true
func EqualBy ¶
func EqualBy[K comparable, V any](m1, m2 map[K]V, eq func(v1, v2 V) bool) bool
EqualBy reports whether two maps contain the same key/value pairs. values are compared using function eq.
🚀 EXAMPLE:
eq := gvalue.Equal[int]
EqualBy(map[int]int{1: 1, 2: 2}, map[int]int{1: 1, 2: 2}, eq) ⏩ true
EqualBy(map[int]int{1: 1}, map[int]int{1: 1, 2: 2}, eq) ⏩ false
EqualBy(map[int]int{}, map[int]int{}, eq) ⏩ true
EqualBy(map[int]int{}, nil, eq) ⏩ true
func Filter ¶
func Filter[M ~map[K]V, K comparable, V any](m M, f func(K, V) bool) M
Filter applies predicate f to each key and value of map m, returns those keys and values that satisfy the predicate f as a new map.
🚀 EXAMPLE:
m := map[int]int{1: 1, 2: 2, 3: 2, 4: 3}
pred := func(k, v int) bool { return (k+v)%2 == 0 }
Filter(m, pred) ⏩ map[int]int{1: 1, 2: 2}
💡 HINT:
- Use FilterKeys if you only need to filter the keys.
- Use FilterValues if you only need to filter the values.
- Use FilterMap if you also want to modify the keys/values during filtering.
func FilterByKeys ¶
func FilterByKeys[M ~map[K]V, K comparable, V any](m M, keys ...K) M
FilterByKeys is a variant of Filter, filters map m by given keys slice, returns a new map containing only the key-value pairs where the key exists in the keys slice.
🚀 EXAMPLE:
m := map[int]int{1: 1, 2: 2, 3: 3, 4: 4}
keys := []int{1, 3, 5}
FilterByKeys(m, keys) ⏩ map[int]int{1: 1, 3: 3}
func FilterByValues ¶
func FilterByValues[M ~map[K]V, K, V comparable](m M, values ...V) M
FilterByValues is a variant of Filter, filters map m by given values slice, returns a new map containing only the key-value pairs where the value exists in the values slice.
🚀 EXAMPLE:
m := map[int]int{1: 10, 2: 20, 3: 10, 4: 30}
values := []int{10, 30}
FilterByValues(m, values) ⏩ map[int]int{1: 10, 3: 10, 4: 30}
func FilterKeys ¶
func FilterKeys[M ~map[K]V, K comparable, V any](m M, f func(K) bool) M
FilterKeys is a variant of Filter, applies predicate f to each key of map m, returns keys that satisfy the predicate f and the corresponding values as a new map.
🚀 EXAMPLE:
m := map[int]int{1: 1, 2: 2, 3: 2, 4: 3}
pred := func(k int) bool { return k%2 == 0 }
FilterKeys(m, pred) ⏩ map[int]int{2: 2, 4: 3}
func FilterMap ¶
func FilterMap[K1, K2 comparable, V1, V2 any](m map[K1]V1, f func(K1, V1) (K2, V2, bool)) map[K2]V2
FilterMap does Filter and Map at the same time, applies function f to each key and value of map m. f returns (K2, V2, bool):
- If true ,the returned key and value will added to the result map[K2]V2.
- If false, the returned key and value will be dropped.
🚀 EXAMPLE:
f := func(k, v int) (string, string, bool) { return strconv.Itoa(k), strconv.Itoa(v), k != 0 && v != 0 }
FilterMap(map[int]int{1: 1, 2: 0, 0: 3}, f) ⏩ map[string]string{"1": "1"}
func FilterMapKeys ¶
func FilterMapKeys[K1, K2 comparable, V any](m map[K1]V, f func(K1) (K2, bool)) map[K2]V
FilterMapKeys is a variant of FilterMap.
🚀 EXAMPLE:
f := func(v int) (string, bool) { return strconv.Itoa(v), v != 0 }
FilterMapKeys(map[int]int{1: 1, 2: 0, 0: 3}, f) ⏩ map[string]int{"1": 1, "2": 0}
func FilterMapValues ¶
func FilterMapValues[K comparable, V1, V2 any](m map[K]V1, f func(V1) (V2, bool)) map[K]V2
FilterMapValues is a variant of FilterMap.
🚀 EXAMPLE:
f := func(v int) (string, bool) { return strconv.Itoa(v), v != 0 }
FilterMapValues(map[int]int{1: 1, 2: 0, 0: 3}, f) ⏩ map[int]string{1: "1", 0: "3"}
func FilterValues ¶
func FilterValues[M ~map[K]V, K comparable, V any](m M, f func(V) bool) M
FilterValues is a variant of Filter, applies predicate f to each value of map m, returns values that satisfy the predicate f and the corresponding keys as a new map.
🚀 EXAMPLE:
m := map[int]int{1: 1, 2: 2, 3: 2, 4: 3}
pred := func(v int) bool { return v%2 == 0 }
FilterValues(m, pred) ⏩ map[int]int{2: 2, 3: 2}
func Indirect ¶
func Indirect[K comparable, V any](m map[K]*V) map[K]V
Indirect returns the values pointed to by the pointers. If the pointer is nil, filter it out of the returned map.
🚀 EXAMPLE:
v1, v2 := "1", "2"
m := map[int]*string{ 1: &v1, 2: &v2, 3: nil}
Indirect(m) ⏩ map[int]string{1: "1", 2: "2"}
💡 HINT: If you want to replace nil pointer with default value, use IndirectOr.
func IndirectOr ¶
func IndirectOr[K comparable, V any](m map[K]*V, fallback V) map[K]V
IndirectOr is variant of Indirect. If the pointer is nil, returns the fallback value instead.
🚀 EXAMPLE:
v1, v2 := "1", "2"
m := map[int]*string{ 1: &v1, 2: &v2, 3: nil}
IndirectOr(m, "nil") ⏩ map[int]string{1: "1", 2: "2", 3: "nil"}
func Intersect ¶
func Intersect[M ~map[K]V, K comparable, V any](ms ...M) M
Intersect returns the intersection of maps as a new map.
💡 NOTE:
- Once the key conflicts, the newer one will replace the older one (DiscardOld), use IntersectBy and ConflictFunc to customize conflict resolution.
- If the result is an empty set, always return an empty map instead of nil
🚀 EXAMPLE:
m := map[int]int{1: 1, 2: 2}
Intersect(m, nil) ⏩ map[int]int{}
Intersect(m, map[int]{3: 3}) ⏩ map[int]int{}
Intersect(m, map[int]{1: 1}) ⏩ map[int]int{1: 1}
Intersect(m, map[int]{1: -1}) ⏩ map[int]int{1: -1} // "1:1" is replaced by the newer "1:-1"
💡 HINT: Use github.com/bytedance/gg/collection/set.Set if you need a set data structure
func IntersectBy ¶
func IntersectBy[M ~map[K]V, K comparable, V any](ms []M, onConflict ConflictFunc[K, V]) M
IntersectBy returns the intersection of maps as a new map, conflicts are resolved by a custom ConflictFunc.
🚀 EXAMPLE:
m := map[int]int{1: 1, 2: 2}
Intersect(m, map[int]{1: -1}) ⏩ map[int]int{1: -1} // "1:1" is replaced by the newer "1:-1"
IntersectBy(gslice.Of(m, map[int]{1: -1}), DiscardOld[int,int]()) ⏩ map[int]int{1: -1} // same as above
IntersectBy(gslice.Of(m, map[int]{1: -1}), DiscardNew[int,int]()) ⏩ map[int]int{1: 1} // "1:1" is kept because it is older
For more examples, see ConflictFunc.
func Invert ¶
func Invert[K, V comparable](m map[K]V) map[V]K
Invert inverts the keys and values of map, and returns a new map. (map[K]V] → map[V]K).
⚠️ WARNING: The iteration of the map is in an indeterminate order, for multiple KV-pairs with the same V, the K retained after inversion is UNSTABLE. If the length of the returned map is equal to the length of the given map, there are no key conflicts. Use InvertBy and ConflictFunc to customize conflict resolution. Use InvertGroup to avoid key loss when multiple keys mapped to the same value.
🚀 EXAMPLE:
Invert(map[string]int{"1": 1, "2": 2}) ⏩ map[int]string{1: "1", 2: "2"},
Invert(map[string]int{"1": 1, "2": 1}) ⏩ ⚠️ UNSTABLE: map[int]string{1: "1"} or map[int]string{1: "2"}
💡 AKA: Reverse
func InvertBy ¶
func InvertBy[K, V comparable](m map[K]V, onConflict ConflictFunc[V, K]) map[V]K
InvertBy inverts the keys and values of map, and returns a new map. (map[K]V] → map[V]K), conflicts are resolved by a custom ConflictFunc.
💡 NOTE: the "oldVal", and "newVal" naming of ConflictFunc are meaningless because of the map's indeterminate iteration order. Further, DiscardOld and DiscardNew are also meaningless.
🚀 EXAMPLE:
InvertBy(map[string]int{"1": 1, "": 1}, DiscardZero(nil) ⏩ map[int]string{1: "1"},
func InvertGroup ¶
func InvertGroup[K, V comparable](m map[K]V) map[V][]K
InvertGroup inverts the map by grouping keys that mapped to the same value into a slice. (map[K]V] → map[V][]K).
⚠️ WARNING: The iteration of the map is in an indeterminate order, for multiple KV-pairs with the same V, the order of K in the slice is UNSTABLE.
🚀 EXAMPLE:
InvertGroup(map[string]int{"1": 1, "2": 2}) ⏩ map[int][]string{1: {"1"}, 2: {"2"}},
InvertGroup(map[string]int{"1": 1, "2": 1}) ⏩ ⚠️ UNSTABLE: map[int][]string{1: {"1", "2"}} or map[int]string{1: {"2", "1"}}
func Items ¶
func Items[K comparable, V any](m map[K]V) tuple.S2[K, V]
Items returns both the keys and values of the map m.
🚀 EXAMPLE:
m := map[int]string{1: "1", 2: "2", 3: "3"}
Items(m) ⏩ []tuple.S2{{2, "2"}, {1, "1"}, {3, "3"}} // ⚠️INDETERMINATE ORDER⚠️
Items(m).Values() ⏩ []int{2, 1, 3}, []string{"2", "1", "3"} // ⚠️INDETERMINATE ORDER⚠️
⚠️ WARNING: The returned items will be in an indeterminate order, use OrderedItems to get them in fixed order.
💡 HINT: The keys and values are returned in the form of a slice of tuples, and the keys slice values slice can be obtained separately through the github.com/bytedance/gg/collection/tuple.S2.Values method.
💡 AKA: KeyValues, KeyAndValues
func Keys ¶
func Keys[K comparable, V any](m map[K]V) []K
Keys returns the keys of the map m.
🚀 EXAMPLE:
m := map[int]string{1: "1", 2: "2", 3: "3", 4: "4"}
Keys(m) ⏩ []int{1, 3, 2, 4} //⚠️INDETERMINATE ORDER⚠️
⚠️ WARNING: The keys will be in an indeterminate order, use OrderedKeys to get them in fixed order.
💡 HINT: If you want to merge key and value to single element, use ToSlice.
func Len ¶
func Len[K comparable, V any](m map[K]V) int
Len returns the length of map m.
💡 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 []map[int]int total1 := SumBy(s, len) // ❌ERROR❌ len (built-in) must be called total2 := SumBy(s, Len[int,int]) // OK
func Load ¶
func Load[K comparable, V any](m map[K]V, k K) goption.O[V]
Load returns the value stored in the map for a key.
If the value was not found in the map. goption.Nil[V]() is returned.
If the given map is nil, goption.Nil[V]() is returned.
💡 HINT: See also LoadAny, LoadAll, LoadSome if you have multiple values to load.
💡 AKA: Get
func LoadAll ¶
func LoadAll[K comparable, V any](m map[K]V, ks ...K) []V
LoadAll returns the all value stored in the map for given keys.
If not all keys are not found in the map, nil is returned. Otherwise, the length of returned values should equal the length of given keys.
🚀 EXAMPLE:
m := map[int]string{1: "1", 2: "2", 3: "3"}
LoadAll(m, 1, 2) ⏩ []string{"1", "2"}
LoadAll(m, 1, 4) ⏩ []
func LoadAndDelete ¶
func LoadAndDelete[K comparable, V any](m map[K]V, k K) goption.O[V]
LoadAndDelete deletes the value for a key, returning the previous value if any.
🚀 EXAMPLE:
var m = map[string]int { "foo": 1 }
LoadAndDelete(m, "bar") ⏩ goption.Nil()
LoadAndDelete(m, "foo") ⏩ goption.OK(1)
LoadAndDelete(m, "foo") ⏩ goption.Nil()
💡 HINT: If you want to delete an element "randomly", use Pop.
func LoadAny ¶
func LoadAny[K comparable, V any](m map[K]V, ks ...K) (r goption.O[V])
LoadAny returns the all value stored in the map for given keys.
If no value is found in the map, goption.Nil[V]() is returned. Otherwise, the first found value is returned.
🚀 EXAMPLE:
m := map[int]string{1: "1", 2: "2", 3: "3"}
LoadAny(m, 1, 2) ⏩ goption.OK("1")
LoadAny(m, 5, 1) ⏩ goption.OK("1")
LoadAny(m, 5, 6) ⏩ goption.Nil[string]()
func LoadBy ¶
func LoadBy[K comparable, V any](m map[K]V, f func(K, V) bool) goption.O[V]
LoadBy find the first value that satisfy the predicate f.
💡 NOTE: LoadBy has O(N) time complexity.
💡 AKA: FindBy, FindValueBy, GetBy, GetValueBy
func LoadItemBy ¶
LoadItemBy find the first key-value pair that satisfy the predicate f.
💡 NOTE: LoadItemBy has O(N) time complexity.
💡 AKA: FindItemBy, GetItemBy
func LoadKey ¶
func LoadKey[K, V comparable](m map[K]V, v V) goption.O[K]
LoadKey find the first key that mapped to the specified value.
💡 NOTE: LoadKey has O(N) time complexity.
🚀 EXAMPLE:
m := map[int]string{1: "1", 2: "2", 3: "3", 4: "4"}
LoadKey(m, "1") ⏩ goption.OK(1)
LoadKey(m, "a") ⏩ goption.Nil[int]()
💡 AKA: FindKey, FindByKey, GetKey, GetByKey
func LoadKeyBy ¶
func LoadKeyBy[K comparable, V any](m map[K]V, f func(K, V) bool) goption.O[K]
LoadKeyBy find the first key that satisfy the predicate f.
💡 NOTE: LoadKeyBy has O(N) time complexity.
💡 AKA: FindKeyBy, GetKeyBy
func LoadOrStore ¶
func LoadOrStore[K comparable, V any](m map[K]V, k K, defaultV V) (v V, loaded bool)
LoadOrStore returns the existing value for the key if present. Otherwise, it stores and returns the given value.
The loaded result is true if the value was loaded, false if stored.
⚠️ WARNING: LoadOrStore panics when a nil map is given.
💡 AKA: setdefault
func LoadOrStoreLazy ¶
func LoadOrStoreLazy[K comparable, V any](m map[K]V, k K, f func() V) (v V, loaded bool)
LoadOrStoreLazy returns the existing value for the key if present. Otherwise, it stores and returns the value that lazy computed by function f.
The loaded result is true if the value was loaded, false if stored.
⚠️ WARNING: LoadOrStoreLazy panics when a nil map is given.
func LoadSome ¶
func LoadSome[K comparable, V any](m map[K]V, ks ...K) []V
LoadSome returns the some values stored in the map for given keys.
🚀 EXAMPLE:
m := map[int]string{1: "1", 2: "2", 3: "3"}
LoadSome(m, 1, 2) ⏩ []string{"1", "2"}
LoadSome(m, 1, 4) ⏩ []string{"1"}
func Map ¶
func Map[K1, K2 comparable, V1, V2 any](m map[K1]V1, f func(K1, V1) (K2, V2)) map[K2]V2
Map applies function f to each key and value of map m. Results of f are returned as a new map.
🚀 EXAMPLE:
f := func(k, v int) (string, string) { return strconv.Itoa(k), strconv.Itoa(v) }
Map(map[int]int{1: 1}, f) ⏩ map[string]string{"1": "1"}
Map(map[int]int{}, f) ⏩ map[string]string{}
💡 HINT:
func MapKeys ¶
func MapKeys[K1, K2 comparable, V any](m map[K1]V, f func(K1) K2) map[K2]V
MapKeys is a variant of Map, applies function f to each key of map m. Results of f and the corresponding values are returned as a new map.
🚀 EXAMPLE:
MapKeys(map[int]int{1: 1}, strconv.Itoa) ⏩ map[string]int{"1": 1}
MapKeys(map[int]int{}, strconv.Itoa) ⏩ map[string]int{}
func MapValues ¶
func MapValues[K comparable, V1, V2 any](m map[K]V1, f func(V1) V2) map[K]V2
MapValues is a variant of Map, applies function f to each values of map m. Results of f and the corresponding keys are returned as a new map.
🚀 EXAMPLE:
MapValues(map[int]int{1: 1}, strconv.Itoa) ⏩ map[int]string{1: "1"}
MapValues(map[int]int{}, strconv.Itoa) ⏩ map[int]string{}
func Max ¶
func Max[K comparable, V constraints.Ordered](m map[K]V) goption.O[V]
Max returns the maximum value of map m.
🚀 EXAMPLE:
Max(map[string]int{"1": 1, "2": 2, "3": 3}) ⏩ goption.OK(3)
💡 NOTE: If the given map is empty, goption.Nil[T]() is returned.
func MaxBy ¶
func MaxBy[K comparable, V any](m map[K]V, less func(V, V) bool) goption.O[V]
MaxBy returns the maximum value of map m determined by function less.
🚀 EXAMPLE:
type Foo struct { Value int }
less := func(x, y Foo) bool { return x.Value < y.Value }
MaxBy(map[string]Foo{"1": {1}, "2": {2}, "3": {3}}, less) ⏩ goption.OK(Foo{3})
💡 NOTE: If the given map is empty, goption.Nil[V]() is returned.
func Min ¶
func Min[K comparable, V constraints.Ordered](m map[K]V) goption.O[V]
Min returns the minimum element of map m.
🚀 EXAMPLE:
Min(map[string]int{"1": 1, "2": 2, "3": 3}) ⏩ goption.OK(1)
💡 NOTE: If the given map is empty, goption.Nil[V]() is returned.
func MinBy ¶
func MinBy[K comparable, V any](m map[K]V, less func(V, V) bool) goption.O[V]
MinBy returns the minimum value of map m determined by function less.
🚀 EXAMPLE:
type Foo struct { Value int }
less := func(x, y Foo) bool { return x.Value < y.Value }
MinBy(map[string]Foo{"1": {1}, "2": {2}, "3": {3}}, less) ⏩ goption.OK(Foo{1})
💡 NOTE: If the given map is empty, goption.Nil[V]() is returned.
func MinMax ¶
func MinMax[K comparable, V constraints.Ordered](m map[K]V) goption.O[tuple.T2[V, V]]
MinMax returns both minimum and maximum elements of map m. If the given map is empty, goption.Nil[tuple.T2[V,V]]() is returned.
MinMax(map[string]int{"1": 1, "2": 2, "3": 3}) ⏩ goption.OK(tuple.T2{1, 3})
💡 AKA: Bound
func MinMaxBy ¶
MinMaxBy returns both minimum and maximum elements of map m determined by function less. If the given map is empty, goption.Nil[tuple.T2[V,V]]() is returned.
🚀 EXAMPLE:
type Foo struct { Value int }
less := func(x, y Foo) bool { return x.Value < y.Value }
m := map[string]Foo{"1": {1}, "2": {2}, "3": {3}}
MinMaxBy(m, less) ⏩ goption.OK(tuple.T2{Foo{1}, Foo{3}})
💡 AKA: BoundBy
func OrderedItems ¶
func OrderedItems[K constraints.Ordered, V any](m map[K]V) tuple.S2[K, V]
OrderedItems is variant of Items, returns the keys and values of the map m in fixed order.
🚀 EXAMPLE:
m := map[int]string{1: "1", 2: "2", 3: "3"}
OrderedItems(m) ⏩ []tuple.S2{{1, "1"}, {2, "2"}, {3, "3"}}
OrderedItems(m).Values() ⏩ []int{1, 2, 3}, []string{"1", "2", "3"}
💡 HINT: The keys and values are returned in the form of a slice of tuples, and the keys slice values slice can be obtained separately through the github.com/bytedance/gg/collection/tuple.S2.Values method.
💡 AKA: SortedItems, SortedKeyValues, SortedKeyAndValues
func OrderedKeys ¶
func OrderedKeys[K constraints.Ordered, V any](m map[K]V) []K
OrderedKeys is the variant of Keys, returns the keys of the map m in fixed order.
🚀 EXAMPLE:
m := map[int]string{1: "1", 2: "2", 3: "3", 4: "4"}
OrderedKeys(m) ⏩ []int{1, 2, 3, 4}
💡 HINT: If you want to merge key and value to single element, use ToOrderedSlice.
💡 AKA: SortedKey
func OrderedValues ¶
func OrderedValues[K constraints.Ordered, V any](m map[K]V) []V
OrderedValues is variant of Values, returns the values of the map m in fixed order.
🚀 EXAMPLE:
m := map[int]string{1: "1", 2: "2", 3: "3", 4: "4"}
OrderedValues(m) ⏩ []string{"1", "2", "3", "4"}
💡 HINT: If you want to merge key and value to single element, use ToOrderedSlice.
💡 AKA: SortedValues
func Peek ¶
func Peek[K comparable, V any](m map[K]V) goption.O[V]
Peek tries to load a "random" element from map m. If m is empty, goption.Nil[V]() is returned.
🚀 EXAMPLE:
var m = map[string]int { "foo": 1 }
Peek(m) ⏩ goption.OK(1)
var m2 = map[string]int {}
Peek(m2) ⏩ goption.Nil()
⚠️ WARNING: As map iteration is indeterminate ordered, we said it is "random".
💡 HINT:
func Pop ¶
func Pop[K comparable, V any](m map[K]V) goption.O[V]
Pop tries to load and DELETE a "random" element from map m. If m is empty, goption.Nil[V]() is returned.
🚀 EXAMPLE:
var m = map[string]int { "foo": 1 }
Pop(m) ⏩ goption.OK(1)
Pop(m) ⏩ goption.Nil()
⚠️ WARNING: As map iteration is indeterminate ordered, we said it is "random".
💡 HINT:
- If you don't want to delete the element, use Peek
- If you want to delete element by key, use LoadAndDelete
- If you want to know the key of poped value, use PopItem
func PtrOf ¶
func PtrOf[K comparable, V any](m map[K]V) map[K]*V
PtrOf returns pointers that point to equivalent values of map m. (map[K]V → map[K]*V).
🚀 EXAMPLE:
PtrOf(map[int]string{1: "1", 2: "2"}) ⏩ map[int]*string{1: (*string)("1"), 2: (*string)("2")}
⚠️ WARNING: The returned pointers do not point to values of the original map, user CAN NOT modify the value by modifying the pointer.
func Reject ¶
func Reject[M ~map[K]V, K comparable, V any](m M, f func(K, V) bool) M
Reject applies predicate f to each key and value of map m, returns those keys and values that do not satisfy the predicate f as a new map.
🚀 EXAMPLE:
m := map[int]int{1: 1, 2: 2, 3: 2, 4: 3}
pred := func(k, v int) bool { return (k+v)%2 != 0 }
Reject(m, pred) ⏩ map[int]int{1: 1, 2: 2}
💡 HINT:
- Use RejectKeys if you only need to reject the keys.
- Use RejectValues if you only need to reject the values.
func RejectByKeys ¶
func RejectByKeys[M ~map[K]V, K comparable, V any](m M, keys ...K) M
RejectByKeys is the opposite of FilterByKeys, removes entries from map m where the key exists in the keys slice, returns a new map containing only the key-value pairs where the key does not exist in the keys slice.
🚀 EXAMPLE:
m := map[int]int{1: 1, 2: 2, 3: 3, 4: 4}
keys := []int{1, 3}
RejectByKeys(m, keys) ⏩ map[int]int{2: 2, 4: 4}
func RejectByValues ¶
func RejectByValues[M ~map[K]V, K, V comparable](m M, values ...V) M
RejectByValues is the opposite of FilterByValues, removes entries from map m where the value exists in the values slice, returns a new map containing only the key-value pairs where the value does not exist in the values slice.
🚀 EXAMPLE:
m := map[int]int{1: 10, 2: 20, 3: 10, 4: 30}
values := []int{10, 30}
RejectByValues(m, values) ⏩ map[int]int{2: 20}
func RejectKeys ¶
func RejectKeys[M ~map[K]V, K comparable, V any](m M, f func(K) bool) M
RejectKeys applies predicate f to each key of map m, returns keys that do not satisfy the predicate f and the corresponding values as a new map.
🚀 EXAMPLE:
m := map[int]int{1: 1, 2: 2, 3: 2, 4: 3}
pred := func(k int) bool { return k%2 != 0 }
RejectKeys(m, pred) ⏩ map[int]int{2: 2, 4: 3}
func RejectValues ¶
func RejectValues[M ~map[K]V, K comparable, V any](m M, f func(V) bool) M
RejectValues applies predicate f to each value of map m, returns values that do not satisfy the predicate f and the corresponding keys as a new map.
🚀 EXAMPLE:
m := map[int]int{1: 1, 2: 2, 3: 2, 4: 3}
pred := func(v int) bool { return v%2 != 0 }
RejectValues(m, pred) ⏩ map[int]int{2: 2, 3: 2}
func Sum ¶
func Sum[K comparable, V constraints.Number](m map[K]V) V
Sum returns the arithmetic sum of the values of map m.
🚀 EXAMPLE:
Sum(map[string]int{"1": 1, "2": 2, "3": 3}) ⏩ 6
💡 NOTE: The returned type is still T, it may overflow for smaller types (such as int8, uint8).
func SumBy ¶
func SumBy[K comparable, V any, N constraints.Number](m map[K]V, f func(V) N) N
SumBy applies function f to each value of map m, returns the arithmetic sum of function result.
func ToOrderedSlice ¶
func ToOrderedSlice[K constraints.Ordered, V, T any](m map[K]V, f func(K, V) T) []T
ToOrderedSlice is variant of ToSlice, the returned slice is in fixed order.
🚀 EXAMPLE:
f := func (k, v int) string {
return fmt.Sprintf("%d: %d", k, v)
}
m := map[int]int{1: 1, 2: 2, 3: 3}
ToOrderedSlice(m, f) ⏩ []string{"1: 1", "2: 2", "3: 3"}
func ToSlice ¶
func ToSlice[K comparable, V, T any](m map[K]V, f func(K, V) T) []T
ToSlice converts the map m to a slice by function f.
⚠️ WARNING: The returned slice will be in an indeterminate order, use ToOrderedSlice to get them in fixed order.
🚀 EXAMPLE:
f := func (k, v int) string {
return fmt.Sprintf("%d: %d", k, v)
}
m := map[int]int{1: 1, 2: 2, 3: 3}
ToSlice(m, f) ⏩ []string{"1: 1", "3: 3", "2: 2"} //⚠️INDETERMINATE ORDER⚠️
💡 HINT:
- If you only need the key slice or value slice, use Keys or Values.
- If you need the key-value pair slice, use Items.
- See also github.com/bytedance/gg/gslice.ToMap.
func TryFilterMap ¶
func TryFilterMap[K1, K2 comparable, V1, V2 any](m map[K1]V1, f func(K1, V1) (K2, V2, error)) map[K2]V2
TryFilterMap is a variant of FilterMap that allows function f to fail (return error).
🚀 EXAMPLE:
f := func(k, v int) (string, string, error) {
ki, kerr := strconv.Atoi(k)
vi, verr := strconv.Atoi(v)
return ki, vi, errors.Join(kerr, verr)
}
TryFilterMap(map[string]string{"1": "1", "2": "2"}, f) ⏩ map[int]int{1: 1, 2: 2}
TryFilterMap(map[string]string{"1": "a", "2": "2"}, f) ⏩ map[int]int{2: 2})
func TryFilterMapKeys ¶
func TryFilterMapKeys[K1, K2 comparable, V any](m map[K1]V, f func(K1) (K2, error)) map[K2]V
TryFilterMapKeys is a variant of FilterMapKeys that allows function f to fail (return error).
🚀 EXAMPLE:
FilterMapKeys(map[string]string{"1": "1", "2": "2"}, strconv.Atoi) ⏩ map[int]string{1: "1", 2: "2"}
FilterMapKeys(map[string]string{"1": "1", "a": "2"}, strconv.Atoi) ⏩ map[int]string{1: "1"}
func TryFilterMapValues ¶
func TryFilterMapValues[K comparable, V1, V2 any](m map[K]V1, f func(V1) (V2, error)) map[K]V2
TryFilterMapValues is a variant of FilterMapValues that allows function f to fail (return error).
🚀 EXAMPLE:
FilterMapValues(map[string]string{"1": "1", "2": "2"}, strconv.Atoi) ⏩ map[string]int{"1": 1, "2": 2}
FilterMapValues(map[string]string{"1": "1", "2": "a"}, strconv.Atoi) ⏩ map[string]int{"1": 1}
func TryMap ¶
func TryMap[K1, K2 comparable, V1, V2 any](m map[K1]V1, f func(K1, V1) (K2, V2, error)) gresult.R[map[K2]V2]
TryMap is a variant of Map that allows function f to fail (return error).
🚀 EXAMPLE:
f := func(k, v int) (string, string, error) {
ki, kerr := strconv.Atoi(k)
vi, verr := strconv.Atoi(v)
return ki, vi, errors.Join(kerr, verr)
}
TryMap(map[string]string{"1": "1"}, f) ⏩ gresult.OK(map[int]int{1: 1})
TryMap(map[string]string{"1": "a"}, f) ⏩ gresult.Err("strconv.Atoi: parsing \"a\": invalid syntax")
💡 HINT:
- Use TryFilterMap if you want to ignore error during mapping.
- Use TryMapKeys if you only need to map the keys.
- Use TryMapValues if you only need to map the values.
func TryMapKeys ¶
func TryMapKeys[K1, K2 comparable, V any](m map[K1]V, f func(K1) (K2, error)) gresult.R[map[K2]V]
TryMapKeys is a variant of MapKeys that allows function f to fail (return error).
🚀 EXAMPLE:
TryMapKeys(map[string]string{"1": "1"}, strconv.Atoi) ⏩ gresult.OK(map[int]string{1: "1"})
TryMapKeys(map[string]string{"a": "1"}, strconv.Atoi) ⏩ gresult.Err("strconv.Atoi: parsing \"a\": invalid syntax")
TryMapKeys(map[string]string{}, strconv.Itoa) ⏩ gresult.OK(map[int]string{})
func TryMapValues ¶
func TryMapValues[K comparable, V1, V2 any](m map[K]V1, f func(V1) (V2, error)) gresult.R[map[K]V2]
TryMapValues is a variant of MapValues that allows function f to fail (return error).
🚀 EXAMPLE:
TryMapValues(map[string]string{"1": "1"}, strconv.Atoi) ⏩ gresult.OK(map[string]int{"1": 1})
TryMapValues(map[string]string{"1": "a"}, strconv.Atoi) ⏩ gresult.Err("strconv.Atoi: parsing \"a\": invalid syntax")
TryMapValues(map[string]string{}, strconv.Itoa) ⏩ gresult.OK(map[string]int{})
func TypeAssert ¶
func TypeAssert[To any, K comparable, From any](m map[K]From) map[K]To
TypeAssert converts values of map from type From to type To by type assertion.
🚀 EXAMPLE:
TypeAssert[int](map[int]any{1: 1, 2: 2}) ⏩ map[int]int{1: 1, 2: 2}
TypeAssert[any](map[int]int{1: 1, 2: 2}) ⏩ map[int]any{1: 1, 2: 2}
TypeAssert[int64](map[int]int{1: 1, 2: 2}) ⏩ ❌PANIC❌
⚠️ WARNING:
- This function may ❌PANIC❌. See github.com/bytedance/gg/gvalue.TypeAssert for more details
func Union ¶
func Union[M ~map[K]V, K comparable, V any](ms ...M) M
Union returns the unions of maps as a new map.
💡 NOTE:
- Once the key conflicts, the newer value always replace the older one (DiscardOld), use UnionBy and ConflictFunc to customize conflict resolution.
- If the result is an empty set, always return an empty map instead of nil
🚀 EXAMPLE:
m := map[int]int{1: 1, 2: 2}
Union(m, nil) ⏩ map[int]int{1: 1, 2: 2}
Union(m, map[int]{3: 3}) ⏩ map[int]int{1: 1, 2: 2, 3: 3}
Union(m, map[int]{2: -1}) ⏩ map[int]int{1: 1, 2: -1} // "2:2" is replaced by the newer "2:-1"
💡 HINT: Use github.com/bytedance/gg/collection/set.Set if you need a set data structure
💡 AKA: Merge, Concat, Combine
func UnionBy ¶
func UnionBy[M ~map[K]V, K comparable, V any](ms []M, onConflict ConflictFunc[K, V]) M
UnionBy returns the unions of maps as a new map, conflicts are resolved by a custom ConflictFunc.
🚀 EXAMPLE:
m := map[int]int{1: 1, 2: 2}
Union(m, map[int]{2: 0}) ⏩ map[int]int{1: 1, 2: 0} // "2:2" is replaced by the newer "2:0"
UnionBy(gslice.Of(m, map[int]int{2: 0}), DiscardOld()) ⏩ map[int]int{1: 1, 2: 0} // same as above
UnionBy(gslice.Of(m, map[int]int{2: 0}), DiscardNew()) ⏩ map[int]int{1: 1, 2: 2} // "2:2" is kept because it is older
For more examples, see ConflictFunc.
func Values ¶
func Values[K comparable, V any](m map[K]V) []V
Values returns the values of the map m.
🚀 EXAMPLE:
m := map[int]string{1: "1", 2: "2", 3: "3", 4: "4"}
Values(m) ⏩ []string{"1", "4", "2", "3"} //⚠️INDETERMINATE ORDER⚠️
⚠️ WARNING: The keys values be in an indeterminate order, use OrderedValues to get them in fixed order.
💡 HINT: If you want to merge key and value to single element, use ToSlice.
Types ¶
type ConflictFunc ¶
type ConflictFunc[K comparable, V any] func(key K, oldVal, newVal V) V
ConflictFunc is used to merge the conflicting key-value of map operations.
Once the key conflicts, the conflicting key and the corresponding values will be passed to this function, and the user can resolve the conflict by returning a new value. Here are some pre-defined ConflictFuncs:
- DiscardOld: this is the default behavior of most map operations
- DiscardNew
- DiscardZero
- DiscardNil
🚀 EXAMPLE:
Union(
map[int]int{1: 1, 2: 2},
map[int]int{ 2: 0}) ⏩ map[int]int{1: 1, 2: 0} // "2:2" is replaced by the newer "2:0"
UnionBy(
gslice.Of(,
map[int]int{1: 1, 2: 2},
map[int]int{ 2: 0}),
DiscardOld()) ⏩ map[int]int{1: 1, 2: 0} // same as above, DiscardOld is the default behavior
UnionBy(
gslice.Of(,
map[int]int{1: 1, 2: 2},
map[int]int{ 2: 0}),
DiscardNew()) ⏩ map[int]int{1: 1, 2: 2} // "2:2" is kept because the newer is always discarded
UnionBy(
gslice.Of(,
map[int]int{ 2: 0},
map[int]int{1: 1, 2: 1},
map[int]int{1: 1, 2: 2},
map[int]int{ 2: 0}),
DiscardZero(nil)) ⏩ map[int]int{1: 1, 2: 2} // "2:2" is kept because 2 is the newest non-zero value
UnionBy(
gslice.Of(,
map[int]int{ 2: 0},
map[int]int{1: 1, 2: 1},
map[int]int{1: 1, 2: 2},
map[int]int{ 2: 0}),
DiscardZero(DiscardNew())) ⏩ map[int]int{1: 1, 2: 1} // "2:1" is kept because 1 is the oldest non-zero value
func DiscardNew ¶
func DiscardNew[K comparable, V any]() ConflictFunc[K, V]
DiscardNew returns a ConflictFunc that always return the older value.
func DiscardNil ¶
func DiscardNil[K comparable, V comparable](fallback ConflictFunc[K, *V]) ConflictFunc[K, *V]
DiscardNil returns a ConflictFunc that always return the non-zero value.
💡 NOTE: If both values are non-nil, the fallback function will be called. If the fallback function is nil, DiscardOld will be called.
func DiscardOld ¶
func DiscardOld[K comparable, V any]() ConflictFunc[K, V]
DiscardOld returns a ConflictFunc that always return the newer value.
func DiscardZero ¶
func DiscardZero[K comparable, V comparable](fallback ConflictFunc[K, V]) ConflictFunc[K, V]
DiscardZero returns a ConflictFunc that always return the non-zero value.
💡 NOTE: If both values are non-zero, the fallback function will be called. If the fallback function is nil, DiscardOld will be called.
💡 HINT: See github.com/bytedance/gg/gvalue.Zero for details of zero value.