Dictionary 合并Golang中的地图

Dictionary 合并Golang中的地图,dictionary,go,merge,slice,Dictionary,Go,Merge,Slice,我需要合并多个映射map1=[id:id\u 1 val:val\u 1],map2=[id:id\u 2 val:val\u 2]和map3=[id:id\u 1,val:val\u 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 dat

我需要合并多个映射
map1=[id:id\u 1 val:val\u 1]
map2=[id:id\u 2 val:val\u 2]
map3=[id:id\u 1,val:val\u 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
切片,内置函数负责(重新)分配

测试它:

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)
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)
输出(在上尝试):

避免重复 请注意,上面的
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"}
m3 := map[string]string{"id_1": "val_3"}

res := merge(m1, m2, m3)
fmt.Println(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)
输出(在上尝试):


我们可以看到
“id_1”:“val_1”
同时包含在
m1
m2
中,但是值
“val_1”
在目标映射中与
“id_1”
键关联的切片中只列出一次。

您尝试了什么?你遇到了什么问题?包括您的代码、输出和/或收到的错误,以及您的预期。此外,停止使用Go 1.7,它甚至不再受支持。最新版本为1.10.2。感谢您用代码更新您的问题。这段代码有什么问题吗?它无法处理切片中的重复值,请尝试使用that@danicheeta是,重复值将被多次列出。这可能是询问者想要的,也可能不是,他对此没有说任何话。@user3809560是否要处理重复的内容?我的意思是,如果相同的
“id\u 1”:“val\u 1”
对包含在多个输入映射中,它是否可以在目标中多次列出,如
“id\u 1”:[“val\u 1”、“val\u x”、“val\u 1”]
?还是要过滤掉这些重复项?@icza,您在srcMap中使用了for循环。它是什么样的控制结构。1中是否支持它。7@user3809560是的,它由Go 1.7支持(但是你真的应该放弃Go 1.7而使用Go 1.10.2)。第二个版本中有3个循环。输入映射切片上的最外层循环(
ms
),输入映射上的第二层循环(
m
),以及结果映射切片值上的最内层循环,以检查是否存在重复。