如果我有一张地图,那么有一种更好的方法可以获得值的切片,然后
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)
}
是否有地图的内置功能? Go包中是否有一个函数,或者这是我必须做的最佳代码?
答案 0 :(得分:49)
不幸的是,没有。没有内置的方法可以做到这一点。
作为旁注,您可以在切片创建中省略capacity参数:
v := make([]string, len(m))
隐含的容量与此处的长度相同。
答案 1 :(得分:44)
作为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)
}
请注意,长度为零(尚未存在元素),但容量(已分配空间)使用m
的元素数进行初始化。这样做是为了append
每次切片v
的容量用完时都不需要分配内存。
您还可以make
没有容量值的切片,让append
为自己分配内存。
答案 2 :(得分:1)
就我目前所知,go没有一种方法可以将字符串/字节连接到结果字符串而不至少制作/ /副本。
你现在必须增长一个[]字节,因为所有的字符串值都是const,然后你必须使用内置的字符串让语言创建一个'祝福的'字符串对象,它将复制缓冲区,因为某些地方可以引用[]字节后面的地址。
如果一个[]字节是合适的,那么你可以通过进行一次分配并执行复制调用你自己来获得一个非常轻微的字节。加入函数。
package main
import (
"fmt"
)
func main() {
m := make(map[int]string)
m[1] = "a" ; m[2] = "b" ; m[3] = "c" ; m[4] = "d"
ip := 0
/* If the elements of m are not all of fixed length you must use a method like this;
* in that case also consider:
* bytes.Join() and/or
* strings.Join()
* They are likely preferable for maintainability over small performance change.
for _, v := range m {
ip += len(v)
}
*/
ip = len(m) * 1 // length of elements in m
r := make([]byte, ip, ip)
ip = 0
for _, v := range m {
ip += copy(r[ip:], v)
}
// r (return value) is currently a []byte, it mostly differs from 'string'
// in that it can be grown and has a different default fmt method.
fmt.Printf("%s\n", r)
}
答案 3 :(得分:1)
不一定更好,但是更干净的方法是定义 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)
}
完整示例:
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
}
简单的解决方案,但有很多陷阱。阅读此博客文章以了解更多详细信息:https://web3.coach/golang-how-to-convert-map-to-slice-three-gotchas
答案 4 :(得分:0)
您可以使用以下maps
软件包:
go get https://github.com/drgrib/maps
那你只需要打电话
values := maps.GetValuesIntString(m)
对于常见的map
组合,它是类型安全的。您可以使用同一包中的generate
工具,为其他任何类型的map
mapper
使用其他类型安全的函数。
完全公开:我是该软件包的创建者。之所以创建它,是因为我发现自己反复为map
重写了这些功能。