Documentation
¶
Overview ¶
Package maps provides map helpers: sorted iteration, grouping, inversion, and merging.
Index ¶
- func Group[K comparable, V any](seq iter.Seq2[K, V]) map[K][]V
- func GroupFunc[K comparable, V any](seq iter.Seq[V], key func(V) K) map[K][]V
- func Invert[M ~map[K]V, K, V comparable](m M) map[V]K
- func Keys[M ~map[K]V, K comparable, V any](m M) []K
- func KeysNatural[M ~map[K]V, K ~string, V any](m M) []K
- func Merge[M ~map[K]V, K comparable, V any](ms ...M) M
- func MergeDeep[M ~map[K]any, K comparable](ms ...M) M
- func MergeFunc[M ~map[K]V, K comparable, V any](resolve func(k K, existing, incoming V) V, ms ...M) M
- func Sorted[M ~map[K]V, K cmp.Ordered, V any](m M) iter.Seq2[K, V]
- func SortedFunc[M ~map[K]V, K comparable, V any](m M, compare func(x, y K) int) iter.Seq2[K, V]
- func Values[M ~map[K]V, K comparable, V any](m M) []V
- func ValuesNatural[M ~map[K]V, K comparable, V ~string](m M) []V
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Group ¶
func Group[K comparable, V any](seq iter.Seq2[K, V]) map[K][]V
Group collects the pairs of `seq` into a map of slices, grouping values by key in encounter order.
Example ¶
package main
import (
"fmt"
xmaps "github.com/gechr/x/maps"
)
func main() {
words := []string{"apple", "banana", "avocado", "blueberry", "cherry"}
byInitial := xmaps.Group(func(yield func(byte, string) bool) {
for _, w := range words {
if !yield(w[0], w) {
return
}
}
})
for initial, group := range xmaps.Sorted(byInitial) {
fmt.Printf("%c: %v\n", initial, group)
}
}
Output: a: [apple avocado] b: [banana blueberry] c: [cherry]
func GroupFunc ¶
func GroupFunc[K comparable, V any](seq iter.Seq[V], key func(V) K) map[K][]V
GroupFunc collects the values of `seq` into a map of slices, grouping values in encounter order by the key returned by `key`.
Example ¶
package main
import (
"fmt"
"slices"
xmaps "github.com/gechr/x/maps"
)
func main() {
words := []string{"go", "rust", "zig", "java", "c"}
byLength := xmaps.GroupFunc(slices.Values(words), func(w string) int {
return len(w)
})
for length, group := range xmaps.Sorted(byLength) {
fmt.Println(length, group)
}
}
Output: 1 [c] 2 [go] 3 [zig] 4 [rust java]
func Invert ¶
func Invert[M ~map[K]V, K, V comparable](m M) map[V]K
Invert returns a new map with the keys and values of `m` swapped. If multiple keys map to the same value, exactly one of them survives as the value in the result, chosen arbitrarily due to map iteration order.
Example ¶
package main
import (
"fmt"
xmaps "github.com/gechr/x/maps"
)
func main() {
codes := map[string]int{"a": 1, "b": 2, "c": 3}
letters := xmaps.Invert(codes)
for code, letter := range xmaps.Sorted(letters) {
fmt.Println(code, letter)
}
}
Output: 1 a 2 b 3 c
func Keys ¶ added in v0.2.18
func Keys[M ~map[K]V, K comparable, V any](m M) []K
Keys returns the keys of `m` as a slice, in indeterminate order.
Example ¶
package main
import (
"fmt"
"slices"
"strings"
xmaps "github.com/gechr/x/maps"
)
func main() {
m := map[string]int{"charlie": 3, "alpha": 1, "beta": 2}
keys := xmaps.Keys(m)
slices.Sort(keys)
fmt.Println(strings.Join(keys, ", "))
}
Output: alpha, beta, charlie
func KeysNatural ¶ added in v0.2.18
KeysNatural returns the string keys of `m` as a slice, sorted in natural order (`item2` before `item10`). See github.com/gechr/x/strings.CompareNatural.
Example ¶
package main
import (
"fmt"
"strings"
xmaps "github.com/gechr/x/maps"
)
func main() {
m := map[string]int{"item10": 10, "item2": 2, "item1": 1}
fmt.Println(strings.Join(xmaps.KeysNatural(m), ", "))
}
Output: item1, item2, item10
func Merge ¶ added in v0.6.2
func Merge[M ~map[K]V, K comparable, V any](ms ...M) M
Merge returns a new map holding the entries of every map in `ms`. If a key appears in more than one map, the value from the last map wins. The inputs are left unmodified.
Example ¶
package main
import (
"fmt"
xmaps "github.com/gechr/x/maps"
)
func main() {
defaults := map[string]string{"host": "localhost", "port": "8080"}
overrides := map[string]string{"port": "9090"}
for k, v := range xmaps.Sorted(xmaps.Merge(defaults, overrides)) {
fmt.Println(k, v)
}
}
Output: host localhost port 9090
func MergeDeep ¶ added in v0.6.2
func MergeDeep[M ~map[K]any, K comparable](ms ...M) M
MergeDeep returns a new map holding the entries of every map in `ms`, merging nested `map[K]any` values recursively. If a key appears in more than one map and either value is not a `map[K]any`, the value from the last map wins. Slices are replaced, not concatenated.
The inputs are left unmodified: every merged level is a new map. Nested maps that appear in only one input are shared with that input, not copied.
Example ¶
package main
import (
"fmt"
xmaps "github.com/gechr/x/maps"
)
func main() {
defaults := map[string]any{
"server": map[string]any{"host": "localhost", "port": 8080},
"debug": false,
}
overrides := map[string]any{
"server": map[string]any{"port": 9090},
}
merged := xmaps.MergeDeep(defaults, overrides)
fmt.Println(merged["debug"])
server, _ := merged["server"].(map[string]any)
for k, v := range xmaps.Sorted(server) {
fmt.Println(k, v)
}
}
Output: false host localhost port 9090
func MergeFunc ¶ added in v0.6.2
func MergeFunc[M ~map[K]V, K comparable, V any]( resolve func(k K, existing, incoming V) V, ms ...M, ) M
MergeFunc returns a new map holding the entries of every map in `ms`. If a key appears in more than one map, `resolve` receives the key, the value merged so far and the incoming value, and returns the value to keep. The inputs are left unmodified.
Example ¶
MergeFunc resolves duplicate keys with a custom function, such as summing the values.
package main
import (
"fmt"
xmaps "github.com/gechr/x/maps"
)
func main() {
monday := map[string]int{"apples": 3, "pears": 1}
tuesday := map[string]int{"apples": 2, "plums": 5}
sum := func(_ string, existing, incoming int) int { return existing + incoming }
for k, v := range xmaps.Sorted(xmaps.MergeFunc(sum, monday, tuesday)) {
fmt.Println(k, v)
}
}
Output: apples 5 pears 1 plums 5
func Sorted ¶
Sorted returns an iterator over the entries of `m` in ascending key order.
Example ¶
package main
import (
"fmt"
xmaps "github.com/gechr/x/maps"
)
func main() {
m := map[string]int{"charlie": 3, "alpha": 1, "beta": 2}
for k, v := range xmaps.Sorted(m) {
fmt.Println(k, v)
}
}
Output: alpha 1 beta 2 charlie 3
func SortedFunc ¶
func SortedFunc[M ~map[K]V, K comparable, V any](m M, compare func(x, y K) int) iter.Seq2[K, V]
SortedFunc returns an iterator over the entries of `m` in the key order determined by `compare`, which follows the cmp.Compare convention.
Example ¶
SortedFunc accepts any comparison following the cmp.Compare convention, such as a descending key order.
package main
import (
"cmp"
"fmt"
xmaps "github.com/gechr/x/maps"
)
func main() {
m := map[int]string{1: "one", 2: "two", 3: "three"}
descending := func(x, y int) int { return cmp.Compare(y, x) }
for k, v := range xmaps.SortedFunc(m, descending) {
fmt.Println(k, v)
}
}
Output: 3 three 2 two 1 one
func Values ¶ added in v0.2.18
func Values[M ~map[K]V, K comparable, V any](m M) []V
Values returns the values of `m` as a slice, in indeterminate order.
Example ¶
package main
import (
"fmt"
"slices"
xmaps "github.com/gechr/x/maps"
)
func main() {
m := map[string]int{"charlie": 3, "alpha": 1, "beta": 2}
values := xmaps.Values(m)
slices.Sort(values)
fmt.Println(values)
}
Output: [1 2 3]
func ValuesNatural ¶ added in v0.2.18
func ValuesNatural[M ~map[K]V, K comparable, V ~string](m M) []V
ValuesNatural returns the string values of `m` as a slice, sorted in natural order (`item2` before `item10`). See github.com/gechr/x/strings.CompareNatural.
Example ¶
package main
import (
"fmt"
"strings"
xmaps "github.com/gechr/x/maps"
)
func main() {
m := map[int]string{10: "item10", 2: "item2", 1: "item1"}
fmt.Println(strings.Join(xmaps.ValuesNatural(m), ", "))
}
Output: item1, item2, item10
Types ¶
This section is empty.