Чи є якийсь простіший / приємніший спосіб отримати фрагмент ключів від карти в 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)
}