在Golang中有一种从地图中获取一片值的好方法吗?

mas*_*ase 70 go

如果我有一张地图m,那么有更好的方法可以获得值的切片

package main
import (
  "fmt"
)

func main() {
    m := make(map[int]string)

    m[1] = "a"
    m[2] = "b"
    m[3] = "c"
    m[4] = "d"

    // Can this be done better?
    v := make([]string, len(m), len(m))
    idx := 0
    for  _, value := range m {
       v[idx] = value
       idx++
    }

    fmt.Println(v)
 }
Run Code Online (Sandbox Code Playgroud)

是否有地图的内置功能?Go包中是否有一个函数,或者这是我必须做的最佳代码?

bla*_*een 71

去1.18

您可以maps.Valuesgolang.org/x/exp包装中使用。

Values 返回映射 m 的值。这些值的顺序不确定。

func main() {
    m := map[int]string{1: "a", 2: "b", 3: "c", 4: "d"}
    v := maps.Values(m)
    fmt.Println(v) 
}
Run Code Online (Sandbox Code Playgroud)

该软件包exp包含实验代码。签名将来可能会也可能不会改变,并且可能会也可能不会升级到标准库。

如果您不想依赖实验包,您可以轻松地自己实现它。事实上,以下代码片段是从exp/maps中复制粘贴的,最初由Ian Lance Taylor编写:

func Values[M ~map[K]V, K comparable, V any](m M) []V {
    r := make([]V, 0, len(m))
    for _, v := range m {
        r = append(r, v)
    }
    return r
}
Run Code Online (Sandbox Code Playgroud)


jim*_*imt 50

很不幸的是,不行.没有内置的方法来做到这一点.

作为旁注,您可以在切片创建中省略capacity参数:

v := make([]string, len(m))
Run Code Online (Sandbox Code Playgroud)

容量与此处的长度相同.


nem*_*emo 46

作为jimt帖子的补充:

您也可以使用append而不是显式地将值分配给它们的索引:

m := make(map[int]string)

m[1] = "a"
m[2] = "b"
m[3] = "c"
m[4] = "d"

v := make([]string, 0, len(m))

for  _, value := range m {
   v = append(v, value)
}
Run Code Online (Sandbox Code Playgroud)

请注意,长度为零(尚未存在元素),但容量(已分配空间)使用元素数初始化m.这样做,因此append每次切片的容量v用完时都不需要分配内存.

你也可以make没有容量值的切片,让我们append为自己分配内存.

  • 小心地将其与上面的答案混合 - 使用 `make([]appsv1.Deployment, len(d))` 之后附加到数组将附加到分配 `len(d) 时创建的一堆空元素` 空项目。 (2认同)

Blo*_*kas 6

不一定更好,但更简洁的方法是定义Slice LENGTH 和 CAPACITY,例如txs := make([]Tx, 0, len(txMap))

    // Defines the Slice capacity to match the Map elements count
    txs := make([]Tx, 0, len(txMap))

    for _, tx := range txMap {
        txs = append(txs, tx)
    }
Run Code Online (Sandbox Code Playgroud)

完整示例:

package main

import (
    "github.com/davecgh/go-spew/spew"
)

type Tx struct {
    from  string
    to    string
    value uint64
}

func main() {
    // Extra touch pre-defining the Map length to avoid reallocation
    txMap := make(map[string]Tx, 3)
    txMap["tx1"] = Tx{"andrej", "babayaga", 10}
    txMap["tx2"] = Tx{"andrej", "babayaga", 20}
    txMap["tx3"] = Tx{"andrej", "babayaga", 30}

    txSlice := getTXsAsSlice(txMap)
    spew.Dump(txSlice)
}

func getTXsAsSlice(txMap map[string]Tx) []Tx {
    // Defines the Slice capacity to match the Map elements count
    txs := make([]Tx, 0, len(txMap))
    for _, tx := range txMap {
        txs = append(txs, tx)
    }

    return txs
}
Run Code Online (Sandbox Code Playgroud)

简单的解决方案,但有很多问题。阅读这篇博文了解更多详情:https : //web3.coach/golang-how-to-convert-map-to-slice-three-gotchas