在Go中是否有更简单/更好的方法从地图中获取键片?

目前我在地图上迭代并复制键到一个切片:

i := 0
keys := make([]int, len(mymap))
for k := range mymap {
    keys[i] = k
    i++
}

当前回答

有一个很酷的lib叫lo

一个lodash风格的Go库,基于Go 1.18+泛型(映射,过滤器,包含,查找…)

有了这个库,你可以做很多方便的操作,如映射,过滤,减少等等。还有一些地图类型的助手

Keys

创建一个映射键数组。

keys := lo.Keys[string, int](map[string]int{"foo": 1, "bar": 2})
// []string{"bar", "foo"}

创建映射值的数组。

values := lo.Values[string, int](map[string]int{"foo": 1, "bar": 2})
// []int{1, 2}

其他回答

例如,

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键的映射,然后用每个方法生成10次键的数组),直接分配数组成员比使用append快了大约20%。

尽管设置容量可以避免重新分配,但append仍然需要做额外的工作,以检查每个追加是否已达到容量。

一个更好的方法是使用append:

keys = []int{}
for k := range mymap {
    keys = append(keys, k)
}

除此之外,你就不走运了——围棋不是一种很有表现力的语言。

有一个很酷的lib叫lo

一个lodash风格的Go库,基于Go 1.18+泛型(映射,过滤器,包含,查找…)

有了这个库,你可以做很多方便的操作,如映射,过滤,减少等等。还有一些地图类型的助手

Keys

创建一个映射键数组。

keys := lo.Keys[string, int](map[string]int{"foo": 1, "bar": 2})
// []string{"bar", "foo"}

创建映射值的数组。

values := lo.Values[string, int](map[string]int{"foo": 1, "bar": 2})
// []int{1, 2}

Vinay Pai的答案的通用版本(1.18+)。

// MapKeysToSlice extract keys of map as slice,
func MapKeysToSlice[K comparable, V any](m map[K]V) []K {
    keys := make([]K, len(m))

    i := 0
    for k := range m {
        keys[i] = k
        i++
    }
    return keys
}