Getting a slice of keys from a map

Go

Go Problem Overview


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++
}

Go Solutions


Solution 1 - Go

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.

Solution 2 - Go

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.

Solution 3 - Go

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]
}

Solution 4 - Go

Go now has generics. We can get the keys of any map with maps.Keys.

Example usage is very simple

	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

It works on go playground https://go.dev/play/p/fkm9PrJYTly

Maybe a few users don't like to import exp packages, we 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
}

Solution 5 - Go

I made a sketchy benchmark on the three methods described in other responses.

Obviously pre-allocating the slice before pulling the keys is faster than appending, but surprisingly, the reflect.ValueOf(m).MapKeys() method is significantly slower than the latter:

❯ go run scratch.go
populating
filling 100000000 slots
done in 56.630774791s
running prealloc
took: 9.989049786s
running append
took: 18.948676741s
running reflect
took: 25.50070649s

Here's the code: https://play.golang.org/p/Z8O6a2jyfTH (running it in the playground aborts claiming that it takes too long, so, well, run it locally.)

Solution 6 - Go

A nicer way to do this would be to use append:

keys = []int{}
for k := range mymap {
    keys = append(keys, k)
}

Other than that, you’re out of luck—Go isn’t a very expressive language.

Solution 7 - Go

Visit https://play.golang.org/p/dx6PTtuBXQW

package main

import (
	"fmt"
	"sort"
)

func main() {
	mapEg := map[string]string{"c":"a","a":"c","b":"b"}
	keys := make([]string, 0, len(mapEg))
	for k := range mapEg {
		keys = append(keys, k)
	}
	sort.Strings(keys)
	fmt.Println(keys)
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSaswat PadhiView Question on Stackoverflow
Solution 1 - GoVinay PaiView Answer on Stackoverflow
Solution 2 - GopeterSOView Answer on Stackoverflow
Solution 3 - GoDenis KreshikhinView Answer on Stackoverflow
Solution 4 - GoMarco JärvinenView Answer on Stackoverflow
Solution 5 - GoNico VillanuevaView Answer on Stackoverflow
Solution 6 - Gouser1804599View Answer on Stackoverflow
Solution 7 - GoLalit SharmaView Answer on Stackoverflow