Чи є якийсь простіший / приємніший спосіб отримати фрагмент ключів від карти в 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 важливо мінімізувати розподіл пам'яті.
mymapце не локальна змінна (і тому вона підлягає зростанню / зменшенню), це єдине правильне рішення - це гарантує, що якщо розмір mymapзмін між ініціалізацією keysта forциклом не буде, позамежні питання.
Це старе питання, але ось два мої центи. Відповідь PeterSO трохи більш стисла, але трохи менш ефективна. Ви вже знаєте, наскільки це буде великим, тому вам навіть не потрібно використовувати додаток:
keys := make([]int, len(mymap))
i := 0
for k := range mymap {
keys[i] = k
i++
}
У більшості ситуацій це, мабуть, не сильно зміниться, але це не набагато більше роботи, і в моїх тестах (використовуючи карту з 1 000 000 випадкових int64 ключів і потім генеруючи масив ключів десять разів з кожним методом), мова йшла про На 20% швидше призначити членів масиву безпосередньо, ніж використовувати додати.
Хоча встановлення ємності виключає перерозподіл, додаток все одно повинен виконати додаткову роботу, щоб перевірити, чи ви досягли ємності для кожного додатка.
for i, k := range mymap{. Таким чином, вам не потрібен i ++?
i, k := range mymap, то iбудуть ключі і kбудуть значення, відповідні цим ключам на карті. Це насправді не допоможе вам заповнити шматок ключів.
Ви також можете взяти масив клавіш з типом []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]
}
[]string?
Приємнішим способом зробити це було б append:
keys = []int{}
for k := range mymap {
keys = append(keys, k)
}
Крім цього, вам не пощастило - Go - це не дуже виразна мова.
keys = make([]int, 0, len(mymap))позбудеться асигнувань, але я очікую, що це все-таки буде повільніше.
Я зробив схематичний орієнтир щодо трьох методів, описаних в інших відповідях.
Очевидно, що попередньо розподілити фрагмент перед перетягуванням клавіш швидше, ніж 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 (запуск його на ігровому майданчику перериває, стверджуючи, що це забирає занадто багато часу, тому добре, запустіть його локально.)
keysAppendфункції ви можете встановити ємність keysмасиву make([]uint64, 0, len(m)), що різко змінило продуктивність цієї функції для мене.
Відвідайте 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)
}