在戈朗中合并地图



我需要合并多个映射map1 = [ id: id_1 val: val_1 ]map2 = [ id: id_2 val: val_2 ]map3 = [id: id_1, val: val_3],以便结果映射应该合并到id值上:

result_map = [id: id_1 val: {val_1, val_3}, id: id_2 var: {val_2}} ]

我尝试过的代码:

var a = make(map[string]interface{})
for _, m := range data {
for _, n := range data {
if m["id"] == n["id"] {
for l, k := range n {
c[l] = k
}
}
}
}

有没有办法做到这一点?我正在使用 Golang 1.7

谢谢

简单合并

是的,它们可以合并,但由于在结果映射中可能有多个值与同一键相关联,因此值类型应为切片,例如map[string][]string

要执行合并,只需在要合并的映射上划清界限,然后将源映射中的每个值附加到与结果映射中同一键关联的切片。

需要注意的一件事是,执行追加后,必须将结果切片重新分配给结果映射中的相同键。

这是一个简单的实现:

func merge(ms ...map[string]string) map[string][]string {
res := map[string][]string{}
for _, m := range ms {
for k, v := range m {
res[k] = append(res[k], v)
}
}
return res
}

merge()函数具有可变参数,这意味着您可以将任意数量的映射传递给它。

请注意,您不需要初始化目标映射中的切片,因为使用尚未包含的键为映射编制索引将导致其类型的零值(对于切片nil(,并且您可以追加到nil切片,内置append()函数负责(重新(分配。

测试它:

m1 := map[string]string{"id_1": "val_1"}
m2 := map[string]string{"id_2": "val_2"}
m3 := map[string]string{"id_1": "val_3"}
res := merge(m1, m2, m3)
fmt.Println(res)

输出(在Go Playground上尝试(:

map[id_1:[val_1 val_3] id_2:[val_2]]

避免重复

请注意,上述merge()不会过滤掉重复项,这意味着如果相同的"id_1": "val_1"对包含在多个输入映射中,它将像"id_1": ["val_1", "val_1", "val_x"]一样在目标中多次列出。要过滤掉此类重复项(仅在目标中列出一次(,我们必须在执行追加之前检查这一点(如果我们以前遇到过,请跳过追加(。

这是可以做到的:

func merge(ms ...map[string]string) map[string][]string {
res := map[string][]string{}
for _, m := range ms {
srcMap:
for k, v := range m {
// Check if (k,v) was added before:
for _, v2 := range res[k] {
if v == v2 {
continue srcMap
}
}
res[k] = append(res[k], v)
}
}
return res
}

测试它:

m1 := map[string]string{"id_1": "val_1"}
m2 := map[string]string{"id_2": "val_2", "id_1": "val_1"}
m3 := map[string]string{"id_1": "val_3"}
res := merge(m1, m2, m3)
fmt.Println(res)

输出(在Go Playground上尝试(:

map[id_1:[val_1 val_3] id_2:[val_2]]

我们可以看到"id_1": "val_1"包含在m1m2中,但值"val_1"在与目标映射中的键相关联的切片中只列出一次"id_1"

最新更新