Is there any simpler/nicer way of getting a slice of keys from a map in Go?
Currently I am iterating over the map and copying the keys to a slice:
i := 0
keys := make([]int, len(mymap))
for k := range mymap {
keys[i] = k
i++
}
This is an old question, but here's my two cents. PeterSO's answer is slightly more concise, but slightly less efficient. You already know how big it's going to be so you don't even need to use append:
keys := make([]int, len(mymap))
i := 0
for k := range mymap {
keys[i] = k
i++
}
In most situations it probably won't make much of a difference, but it's not much more work, and in my tests (using a map with 1,000,000 random int64
keys and then generating the array of keys ten times with each method), it was about 20% faster to assign members of the array directly than to use append.
Although setting the capacity eliminates reallocations, append still has to do extra work to check if you've reached capacity on each append.
For example,
package main
func main() {
mymap := make(map[int]string)
keys := make([]int, 0, len(mymap))
for k := range mymap {
keys = append(keys, k)
}
}
To be efficient in Go, it's important to minimize memory allocations.
You also can take an array of keys with type []Value
by method MapKeys
of struct Value
from package "reflect":
package main
import (
"fmt"
"reflect"
)
func main() {
abc := map[string]int{
"a": 1,
"b": 2,
"c": 3,
}
keys := reflect.ValueOf(abc).MapKeys()
fmt.Println(keys) // [a b c]
}
Go now has generics. You can get the keys of any map with maps.Keys
.
Example usage:
intMap := map[int]int{1: 1, 2: 2}
intKeys := maps.Keys(intMap)
// intKeys is []int
fmt.Println(intKeys)
strMap := map[string]int{"alpha": 1, "bravo": 2}
strKeys := maps.Keys(strMap)
// strKeys is []string
fmt.Println(strKeys)
maps
package is found in golang.org/x/exp/maps
. This is experimental and outside of Go compatibility guarantee. They aim to move it into the std lib in Go 1.19 the future.
Playground: https://go.dev/play/p/fkm9PrJYTly
For those who don't like to import exp packages, you can copy the source code:
// Keys returns the keys of the map m.
// The keys will be an indeterminate order.
func Keys[M ~map[K]V, K comparable, V any](m M) []K {
r := make([]K, 0, len(m))
for k := range m {
r = append(r, k)
}
return r
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With