How to iterate through a map in Golang in order?
You can make it a little faster by preallocating keys
because you know its length:
func sortedKeys(m map[Key]Value) ([]Key) {
keys := make([]Key, len(m))
i := 0
for k := range m {
keys[i] = k
i++
}
sort.Keys(keys)
return keys
}
Replace Key
and Value
with your key and value types (including the sort
line). cough generics cough
Edit: Go 1.18 is finally getting generics! Here's the generic version:
// Ordered is a type constraint that matches any ordered type.
// An ordered type is one that supports the <, <=, >, and >= operators.
//
// Note the generics proposal suggests this type will be available from
// a standard "constraints" package in future.
type Ordered interface {
type int, int8, int16, int32, int64,
uint, uint8, uint16, uint32, uint64, uintptr,
float32, float64,
string
}
func sortedKeys[K Ordered, V any](m map[K]V) ([]K) {
keys := make([]K, len(m))
i := 0
for k := range m {
keys[i] = k
i++
}
sort.Slice(keys, func(i, j int) bool { return keys[i] < keys[j] })
return keys
}
Playground example
Collect all keys, sort them and iterate your map by key, like the following:
keys := make([]int, 0)
for k, _ := range romanNumeralDict {
keys = append(keys, k)
}
sort.Ints(keys)
for _, k := range keys {
fmt.Println(k, romanNumeralDict[k])
}
If execution speed isn't a big concern, you can get a sorted array of keys using MapKeys
.
In this example, the keys are of type string
:
keys := reflect.ValueOf(myMap).MapKeys()
keysOrder := func(i, j int) bool { return keys[i].Interface().(string) < keys[j].Interface().(string) }
sort.Slice(keys, keysOrder)
// process map in key-sorted order
for _, key := range keys {
value := myMap[key.Interface().(string)]
fmt.Println(key, value)
}
- See: Getting a slice of keys from a map
- Warning: This bypasses some compile-time type-safety (panics if not a map)
- You'll need to cast each key in order to get its raw value:
key.Interface().(string)