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

时间:2017-12-19 07:13:16

标签: python python-3.x dictionary nested

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

Route::get('aset/{id}', 'TransaksiController@aset_view')->where('id', '[0-9]+');

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},
....
}

但它只是为我复制dict2。

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

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

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

3 个答案:

答案 0 :(得分: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的情况下完成了它的工作。

答案 1 :(得分:0)

HttpResponseMessage response = new HttpResponseMessage()
{
    Content = new StringContent(
                responseData,
                Encoding.UTF8,
                "text/plain"
            )
};

答案 2 :(得分: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}。

我希望它足够清楚!