将字典列表与一个键值匹配相结合

combine a list of dictionaries with one key value match

listofdicts = [
{
    "if-e0": "e0",
    "ip-add-e0": "192.168.1.1",
    "name": "host1"
},
{
    "if-e1": "e1",
    "ip-add-e1": "192.168.2.1",
    "name": "host1"
},
{
    "if-e1": "e1",
    "ip-add-e1": "172.16.1.1",
    "name": "host2"
},
{
    "if-e2": "e2",
    "ip-add-e2": "172.16.2.1",
    "name": "host2"
}]

预期结果:

listofdicts = [
{
    "if-e0": "e0",
    "ip-add-e0": "192.168.1.1",
    "if-e1": "e1",
    "ip-add-e1": "192.168.2.1",
    "name": "host1"
},
{
    "if-e1": "e1",
    "ip-add-e1": "172.16.1.1",
    "if-e2": "e2",
    "ip-add-e2": "172.16.2.1",
    "name": "host2"
}]

一直在努力使这项工作成功,但还没有成功,实际列表中有超过 60K 个具有独特和匹配主机的字典。

它可能更容易解决,但对我来说,这是过去几个小时的噩梦。

感谢您的帮助。

此致, 阿维纳什

a = []

for i in listofdicts:
    if i["name"] not in a:
        a.append(i["name"])
        print(i)

图论在这里似乎很有用。

要解决这个问题,您需要构建一个图,其中每个顶点都与您输入列表中的一个字典相关。

如果在相应的字典中有一个共同的键值对,那么两个顶点之间应该有一条边(更具体地说,对于字典 d1d2 应该有一条边,如果 len(set(d1.items()).intersection(d2.items())) != 0 或者,更简单的,if set(d1.items()).intersection(d2.items())。条件表示在 d1d2 的项目集的交集中至少有一个键值对)。

图建好后,你需要找到所有的连接组件(这是一个非常简单的DFS(深度优先搜索),如果你不熟悉图算法,你可以google它) .每个连接组件的字典应该合并为一个:每个组件应该有一个结果字典。这些生成的词典列表就是您的答案。

以下是如何组合一些词典的示例:

connectivity_component_dicts = [{...}, ...]
resulting_dict = {**d for d in connectivity_component_dicts}
# Note that the greater the index of `d` in `connectivity_component_dicts`,
# the higher priority its keys have if there are same keys in some dicts.

@Kolay.Ne 大家好, 它确实适用于一个非常基本的捕获。图形方法非常适合解决它,尽管我使用了以下有效的方法 n:

for d in listofdicts:
    x = listofdicts.index(d)
    for y in range(len(listofdicts)):
        k = 'name'
        if y != x and y < len(listofdicts):
            if listofdicts[x][k] == listofdicts[y][k]:
                dc = copy.deepcopy(listofdicts[y])
                listofdicts[x].update(dc)
                listofdicts.remove(dc)

可能是其他方法来解决它,我确定 pathonic 方法将只有几行,这解决了我手头工作的问题。

感谢 kolay.Ne 快速响应并尝试提供帮助,图形方法也很棒,需要专业编码,并且肯定会更具可扩展性。