如何将两个相似的嵌套字典合并为一个,每个字典都有一些共享和独特的嵌套元素(Python)?

问题描述 投票:1回答:3

我有两个大型嵌套字典,我需要合并为一个:

dict1={
1: {"trait1: 32", "trait2": 43, "trait 3": 98},
2: {"trait1: 38", "trait2": 40, "trait 3": 95},
....
}

dict2={
1: {"trait1: 32", "trait2": 43, "trait 4": 54},
2: {"trait1: 38", "trait2": 40, "trait 4": 56},
....
}

而我想得到的是:

dict3={
1: {"trait1: 32", "trait2": 43, "trait 3": 98, "trait 4": 54},
2: {"trait1: 38", "trait2": 40, "trait 3": 95, "trait 4": 56},
....
}

我尝试过使用:

dict3=dict(list(dict1.items()) + list(dict2.items()))

但它只是为我复制dict2。

我也试过像这样循环“主”键(我复制了第一个字典成为最终输出):

dict3 = dict(dict1)

for key1 in dict3:
    for key2 in dict2:
        dict3[key1].update({"trait4": dict2[key2]["trait4"]})

但这不起作用,只有每一个条目在输出中按预期出现。而且我很确定我的做法是错误的。任何帮助表示赞赏!

python python-3.x dictionary nested
3个回答
2
投票

要实现您的目标,您所要做的就是检查字典是否包含密钥。你应该定义一个函数,例如update_keys(),它将采用两个参数:dict1dict2

要检查dictionary是否有key只需写(如this question中所述):

if key in dictionary:
    # Action you want to take if dictionary has key.

因此,您的解决方案将如下所示(请注意,deepcopy函数是从复制模块导入的,如下面的Update 1中所述):

#!/usr/bin/env python3

from copy import deepcopy

def update_keys(dict1, dict2):
    result_dict = deepcopy(dict1)
    for key in dict2:
        if key in result_dict:
            for sub_key in dict2[key]:
                result_dict[key].update({sub_key: dict2[key][sub_key]})
        else: 
            result_dict.update({key: dict2[key]})
    return result_dict

dict3 = update_keys(dict1, dict2)

为了澄清事情,您可以使用dictionary.items()中提到的this question来迭代使用值,因为在嵌套循环和多个if语句中,您可能会在所有变量之间丢失。

#!/usr/bin/env python3

from copy import deepcopy

dict1={
1: {"trait1": 32, "trait2": 43, "trait3": 98},
2: {"trait1": 38, "trait2": 40, "trait3": 95}
}

dict2={
1: {"trait1": 32, "trait2": 43, "trait4": 54},
2: {"trait1": 38, "trait2": 40, "trait4": 56}
}

def update_keys(dict_one, dict_two):
    result_dict = deepcopy(dict_one)
    for key, value in dict_two.items():
        if key in result_dict:
            for sub_key, sub_value in value.items():
                if sub_key not in result_dict[key]:
                    result_dict[key].update({sub_key: sub_value})
        else:
            result_dict.update({key: value})
    return result_dict

dict3 = update_keys(dict1, dict2)

更新1:感谢@shash678我可以改进我的答案。早先将字典传递给方法并通过分配新值创建浅拷贝来制作副本,如本question topic中所述。因此,如果要保留dict1,则必须导入copy模块并使用deepcopy()函数。感谢@shash678,这个答案在不修改dict1的情况下完成了它的工作。


0
投票

如果两个dicts中的键可以假设相同(对于python 3.5+),我想提出一个非常方便的合并。如果密钥都相同,我们可以简单地这样做:

merged_dict = {}
for key in dict1.keys():
    merged_dict[key] = {**dict1[key], **dict2[key]}
# result: 
# merged_dict is {1: {'trait1': 32, 'trait2': 43, 'trait3': 98, 'trait4': 54},
#                 2: {'trait1': 38, 'trait2': 40, 'trait3': 95, 'trait4': 56}}

在dict前面的双星解包它,从Python 3.5开始,这种语法将允许我们解析dict文字中的dicts,有效地合并它们。我在这里假设在原始字典的每个值中都是字典本身。您可以直接以某种方式解压缩嵌套dicts(而不是使用for循环),但我不知道如何(如果有人,请评论!)。

如果我们假设键可能不同,我们必须添加一些东西,但是没有嵌套结构,所以我认为它仍然很简单。例如,假设dict2具有键/值对{3:{'trait5':435,'trait7':42}}。

# find the shared keys, i.e. the intersection of the key sets
shared_keys = set(dict1.keys()).intersection(set(dict2.keys()))
merged_dict = {}
for key in shared_keys:
    merged_dict[key] = {**dict1[key], **dict2[key]}
# now add any key/value pairs only in dict1
for key in set(dict1.keys()) - shared_keys:
    merged_dict[key] = {**dict1[key]}
# and the same for dict2
for key in set(dict2.keys()) - shared_keys:
    merged_dict[key] = {**dict2[key]}
# result:
# merged_dict is {1: {'trait1': 32, 'trait2': 43, 'trait3': 98, 'trait4': 54}, 
#                 2: {'trait1': 38, 'trait2': 40, 'trait3': 95, 'trait4': 56}},
#                 3: {'trait5': 435, 'trait7': 42}}

我使用set操作来获取共享密钥,然后仅在dict1和dict2中获取密钥。例如,{1,2,3}和{1,2}的交集是{1,2},而集合差异{1,2,3} - {1,2} = {3}。

我希望它足够清楚!


0
投票
def merge_dict(x,y):
    keys = list(set(x.keys() + y.keys()))
    result = {}
    for key in keys:
        if key in x.keys():
            z = x[key].copy()
            if key in y.keys():
                z.update(y[key])
            result[key] = z
        else:
            result[key] = y[key]
        result[k] = z
    return result


dict3 = merge_dict(dict1,dict2)
© www.soinside.com 2019 - 2024. All rights reserved.