有没有更简单/更好的方法从Go中的地图获取一片键?
目前我正在遍历地图并将密钥复制到切片:
i := 0
keys := make([]int, len(mymap))
for k := range mymap {
keys[i] = k
i++
}
Run Code Online (Sandbox Code Playgroud)
Vin*_*Pai 328
这是一个老问题,但这是我的两分钱.PeterSO的答案稍微简洁一些,但效率稍差.你已经知道它有多大,所以你甚至不需要使用append:
keys := make([]int, len(mymap))
i := 0
for k := range mymap {
keys[i] = k
i++
}
Run Code Online (Sandbox Code Playgroud)
在大多数情况下,它可能不会产生太大的影响,但它不是更多的工作,并且在我的测试中(使用带有1,000,000个随机int64密钥的地图,然后使用每种方法生成密钥数组十次),它是关于分配成员直接比使用追加快20%.
尽管设置容量会消除重新分配,但追加仍然需要做额外的工作来检查每个附加是否达到了容量.
pet*_*rSO 176
例如,
package main
func main() {
mymap := make(map[int]string)
keys := make([]int, 0, len(mymap))
for k := range mymap {
keys = append(keys, k)
}
}
Run Code Online (Sandbox Code Playgroud)
为了在Go中高效,最小化内存分配很重要.
bla*_*een 106
Go 现在有了泛型。您可以使用 获取任何地图的钥匙maps.Keys。
用法示例:
intMap := map[int]int{1: 1, 2: 2}
intKeys := maps.Keys(intMap)
// intKeys is []int
fmt.Println(intKeys)
strMap := map[string]int{"alpha": 1, "bravo": 2}
strKeys := maps.Keys(strMap)
// strKeys is []string
fmt.Println(strKeys)
Run Code Online (Sandbox Code Playgroud)
maps包位于golang.org/x/exp/maps. 这是实验性的,超出了 Go 兼容性保证。他们的目标是在未来将其移至Go 1.19 的标准库中。
游乐场:https://go.dev/play/p/fkm9PrJYTly
对于那些不喜欢导入 exp 包的人,这里是源代码(最初由Ian Lance Taylor编写),如您所见,它非常简单:
// Keys returns the keys of the map m.
// The keys will be an indeterminate order.
func Keys[M ~map[K]V, K comparable, V any](m M) []K {
r := make([]K, 0, len(m))
for k := range m {
r = append(r, k)
}
return r
}
Run Code Online (Sandbox Code Playgroud)
注意:在 Go 1.21 中,包的一部分maps已移至标准库中,但maps.Keys. 有关详细信息,请参阅 Go 问题图:删除 Go 1.21 的键和值tl;dr 该Keys方法最终可能会具有不同的签名。所以在 Go 1.21 中,这里提出的解决方案(使用x/exp/maps或复制源)仍然适用。
Den*_*hin 70
您还可以[]Value通过包"reflect"中MapKeys的struct 方法获取类型的键数组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]
}
Run Code Online (Sandbox Code Playgroud)
rig*_*old 11
一个更好的方法是使用append:
keys = []int{}
for k := range mymap {
keys = append(keys, k)
}
Run Code Online (Sandbox Code Playgroud)
除此之外,你运气不好 - Go不是一个非常富有表现力的语言.
我对其他回复中描述的三种方法做了一个粗略的基准测试。
显然,在拉动键之前预先分配片比appending 快,但是令人惊讶的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
Run Code Online (Sandbox Code Playgroud)
这是代码:https : //play.golang.org/p/Z8O6a2jyfTH (在操场上运行它会中止宣称它花费的时间太长,所以,可以在本地运行它。)
假设map是类型map[int]string,您可以使用标准库中的实验性映射包获取键和值:
package main
import (
"fmt"
"golang.org/x/exp/maps"
)
func main() {
mymap := map[int]string{1: "foo", 2: "bar", 3: "biz"}
fmt.Println(maps.Keys(mymap))
fmt.Println(maps.Values(mymap))
}
Run Code Online (Sandbox Code Playgroud)
输出:
[2 3 1]
[bar biz foo]
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
171356 次 |
| 最近记录: |