在Golang中合并地图 [英] Merge Maps in Golang

查看:71
本文介绍了在Golang中合并地图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I need to merge multiple maps map1 = [ id: id_1 val: val_1 ], map2 = [ id: id_2 val: val_2 ] and map3 = [id: id_1, val: val_3] such that the result map should be merged on the id values:

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

Is there a way this can be done? Am using Golang 1.7

谢谢

推荐答案

简单合并

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

要进行合并,只需在要合并的地图上进行调整,然后将源地图中的每个值附加到与结果地图中相同键相关联的切片.

To do the merge, simply range over the maps to be merged, and append each value from the source maps to the slice associated with the same key in the result map.

要注意的一件事是,一旦执行附加操作,就必须将结果切片分配回结果图中的同一键.

One thing to look out for is that once you do the append, you have to assign back the result slice to the same key in the result map.

这是一个简单的实现:

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()函数具有可变参数,这意味着您可以向其传递任意数量的地图.

This merge() function has a variadic parameter, which means you may pass any number of maps to it.

请注意,您不需要初始化目标地图中的切片,因为使用尚未插入的键索引地图会导致

Note that you don't need to initialize the slices in the target map, as indexing a map with a key that is not yet in it will result in the zero value of its type (which is nil for slices), and you may append to a nil slice, the builtin append() function takes care of (re-)allocations.

测试:

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)

输出(在游乐场上尝试):

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

避免重复

请注意,上面的merge()不会过滤出重复项,这意味着如果多个输入映射中包含相同的"id_1": "val_1"对,它将在目标中多次列出,例如"id_1": ["val_1", "val_1", "val_x"].要过滤掉这些重复项(仅在目标中将其列出一次),我们必须在执行附加操作之前进行检查(如果之前遇到过,请跳过附加操作).

Avoiding duplicates

Note that the above merge() will not filter out duplicates, meaning if the same "id_1": "val_1" pair is contained in multiple input maps, it will be listed multiple times in the target like "id_1": ["val_1", "val_1", "val_x"]. To filter out such duplicates (to only list it once in the target), we have to check this before doing the append (and if we've encountered it before, skip the append).

这是可以完成的方法:

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)

输出(在游乐场上尝试):

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

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

We can see that "id_1": "val_1" was included both in m1 and m2, yet the value "val_1" is only listed once in in the slice associated with "id_1" key in the target map.

这篇关于在Golang中合并地图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆