Есть ли более простой/лучший способ получить кусочек ключей с карты в Go?
В настоящее время я повторяю карту и копирую ключи в срез:
i := 0
keys := make([]int, len(mymap))
for k := range mymap {
keys[i] = k
i++
}
Есть ли более простой/лучший способ получить кусочек ключей с карты в Go?
В настоящее время я повторяю карту и копирую ключи в срез:
i := 0
keys := make([]int, len(mymap))
for k := range mymap {
keys[i] = k
i++
}
Например,
package main
func main() {
mymap := make(map[int]string)
keys := make([]int, 0, len(mymap))
for k := range mymap {
keys = append(keys, k)
}
}
Чтобы эффективно работать в Go, важно минимизировать выделение памяти.
Это старый вопрос, но здесь мои два цента. Ответ PeterSO немного более краткий, но немного менее эффективный. Вы уже знаете, как сильно это будет, поэтому вам даже не нужно использовать append:
keys := make([]int, len(mymap))
i := 0
for k := range mymap {
keys[i] = k
i++
}
В большинстве ситуаций это, вероятно, не будет иметь большого значения, но это не намного больше работает, и в моих тестах (используя карту с 1 000 000 случайных клавиш int64
, а затем генерируя массив ключей десять раз с каждым метод), было примерно на 20% быстрее назначать элементы массива напрямую, чем использовать append.
Несмотря на то, что установка емкости устраняет перераспределение, добавьте еще одну дополнительную работу, чтобы проверить, достигли ли вы емкости на каждом добавлении.
Вы также можете взять массив ключей с типом []Value
методом MapKeys
структуры Value
из пакета "отразить":
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]
}
Лучшим способом сделать это будет использование append
:
keys = []int{}
for k := range mymap {
keys = append(keys, k)
}
Кроме того, вы не повезло - Go не очень выразительный язык.
Я сделал схематичный тест по трем методам, описанным в других ответах.
Очевидно, что предварительное выделение фрагмента перед нажатием клавиш происходит быстрее, чем append
, но, что удивительно, метод reflect.ValueOf(m).MapKeys()
значительно медленнее, чем последний:
❯ 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
Вот код: https://play.golang.org/p/Z8O6a2jyfTH (запуск его на детской площадке прерывается, утверждая, что это занимает слишком много времени, поэтому, хорошо, запустите его локально.)
Посетите 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)
}