是否有更简单/更好的方式从Go中的地图获取一片键?
目前,我正在迭代地图并将密钥复制到切片:
i := 0
keys := make([]int, len(mymap))
for k := range mymap {
keys[i] = k
i++
}
答案 0 :(得分:291)
这是一个老问题,但这是我的两分钱。 PeterSO的答案稍微简洁一些,但效率稍差。你已经知道它有多大,所以你甚至不需要使用追加:
keys := make([]int, len(mymap))
i := 0
for k := range mymap {
keys[i] = k
i++
}
在大多数情况下,它可能不会产生太大的影响,但是在我的测试中(使用带有1,000,000个随机int64
密钥的地图然后生成密钥数组十次)使用每种方法),直接分配数组成员比使用append快20%。
虽然设置容量会消除重新分配,但追加仍然需要做额外的工作来检查你是否已达到每个附加的容量。
答案 1 :(得分:158)
例如,
package main
func main() {
mymap := make(map[int]string)
keys := make([]int, 0, len(mymap))
for k := range mymap {
keys = append(keys, k)
}
}
为了提高Go的效率,最小化内存分配非常重要。
答案 2 :(得分:61)
您还可以从包&#34中采用结构[]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]
}
答案 3 :(得分:9)
更好的方法是使用append
:
keys = []int{}
for k := range mymap {
keys = append(keys, k)
}
除此之外,你运气不好 - Go不是一个非常富有表现力的语言。
答案 4 :(得分:4)
我对其他回复中描述的三种方法进行了粗略的基准测试。
显然,在拉动键之前预先分配切片比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 (在操场上运行它会声称它花费的时间太长,因此,可以在本地运行它。)
答案 5 :(得分:0)
访问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)
}