it-swarm.cn

将地图的所有元素复制到另一个元素中

特定

var dst, src map[K]V

我可以将src中的所有条目复制到dst

for k, v := range src {
    dst[k] = v
}

有没有比较惯用的方法呢?

copy仅适用于切片(和string作为源)。

60
Mike Samuel

对我来说这看起来是一个非常好的方式。我不认为将一张地图复制到另一张地图就足以拥有单线解决方案。

45
Lily Ballard

使用简单的for range循环是最有效的解决方案。

请注意,内置copy不能将src的内存复制到dst的地址,因为它们可能具有完全不同的内存布局。地图增长以适应存储在其中的项目数量。因此,例如,如果你有一个包含一百万个元素的地图,它占用的内存比新创建的新地图要多得多,因此内置的copy不能只是在不分配新内存的情况下复制内存。

如果您的地图很大,您可以加快复制元素,如果您可以创建具有足够大容量的目标地图,以避免重新分配和重新分配(初始容量不限制其大小),例如:

dst := make(map[K]V, len(src))

for k, v := range src {
    dst[k] = v
}

如果性能不是问题(例如,您正在使用小地图),可以使用 reflect package创建一般解决方案:

func MapCopy(dst, src interface{}) {
    dv, sv := reflect.ValueOf(dst), reflect.ValueOf(src)

    for _, k := range sv.MapKeys() {
        dv.SetMapIndex(k, sv.MapIndex(k))
    }
}

此解决方案不会检查参数是否真的是映射,以及目标不是nil。测试它:

m1 := map[int]string{1: "one", 2: "two"}
m2 := map[int]string{}
MapCopy(m2, m1)
fmt.Println(m2)

m3 := map[string]int{"one": 1, "two": 2}
m4 := map[string]int{}
MapCopy(m4, m3)
fmt.Println(m4)

输出(在 Go Playground上尝试 ):

map[1:one 2:two]
map[one:1 two:2]
7
icza

你可以使用 github.com/linkosmos/mapop

input :=  map[string]interface{}{
  "Key1": 2,
  "key3": nil,
  "val": 2,
  "val2": "str",
  "val3": 4,
}

input2 := map[string]interface{}{
  "a2": "str",
  "a3": 4,
}

input = mapop.Merge(input, input2)

input{"Key1": 2, "key3": nil, "val": 2, "val2": "str", "val3": 4, "a2": "str", "a3": 4}
2
Ernestas Poskus