简体   繁体   English

您如何将两个相似的嵌套字典合而为一,每个字典都有一些共享且唯一的嵌套元素(Python)?

[英]How do you combine two similar nested dictionaries into one, each with some shared and unique nested elements (Python)?

I have two large nested dictionaries that I need to merge into a single one: 我有两个大型嵌套字典,需要将它们合并为一个字典:

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

and

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

and what I'd like to get is this: 我想得到的是:

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

I've tried using: 我试过使用:

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

But it simply copies dict2 for me. 但这只是为我复制了dict2。

I've also tried looping through the "main" keys like this(I copied the first dictionary to become the final output): 我也尝试过像这样遍历“主”键(我复制了第一个字典成为最终输出):

dict3 = dict(dict1)

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

But that doesn't work, only every few entries come out as expected in the output. 但这是行不通的,只有每隔几个条目就会按预期输出。 And I'm fairly sure that my approach is wrong on this. 我非常确定我的方法在这方面是错误的。 Any help is appreciated! 任何帮助表示赞赏!

To achieve your goal all you have to do is to check if dictionary contains key. 要实现您的目标,您要做的就是检查字典中是否包含密钥。 You should define a function for example update_keys() which would take two arguments: dict1 and dict2 . 您应该为例如update_keys()定义一个函数,该函数将update_keys()两个参数: dict1dict2

To check if dictionary has key simply write (as mentioned in this question ): 要检查dictionary是否具有key只需编写(如本问题所述 ):

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

Therefore your solution would look like this ( note that deepcopy function is imported from copy module, as mentioned in Update 1 below ): 因此,您的解决方案将如下所示( 请注意,如下面的更新1所述,Deepcopy函数是从复制模块导入的 ):

#!/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)

also to clarify things, you could iterate using values by using dictionary.items() like mentioned in this question , because in nested loop and multiple if statements you might get lost between all the variables. 同样为了弄清楚事情,您可以像本问题中提到的那样通过使用dictionary.items()来迭代使用值,因为在嵌套循环和多个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)

Update 1: Thanks to @shash678 I could improve my answer. 更新1:感谢@ shash678,我可以改善我的答案。 Earlier passing dictionary to method and making copy by assigning new value created shallow copy as mentioned in this question topic . 较早地将字典传递给方法,并通过分配新值来进行复制,从而创建了浅副本,如本问题主题所述 Therefore if dict1 is to be preserved, importing copy module and using deepcopy() function from it is necessary. 因此,如果要保留dict1,则必须导入copy模块并从中使用deepcopy()函数。 Thanks to @shash678 , this answer does its job without modifying dict1. 感谢@ shash678 ,此答案无需修改dict1即可完成其工作。

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)

I would like to propose a merging that is very handy if the keys in both dicts can be assumed to be the same (for python 3.5+). 如果两个字典中的键可以假定是相同的(对于python 3.5+),我想提出一个非常方便的合并方法。 If the keys are all the same, we may simply do this: 如果密钥都相同,我们可以简单地这样做:

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

The double stars in front of a dict unpacks it, and since Python 3.5, this syntax will allow us to unpack dicts inside of a dict literal, effectively merging them. 字典前面的双星将其解包,并且从Python 3.5开始,此语法将使我们能够将dict文本中的字典解包,从而有效地合并它们。 I am here assuming that in each value of the original dict is a dictionary itself. 我在这里假设原始字典的每个值都是一个字典本身。 It's possible that you can do the unpacking of the nested dicts directly in some way (instead of using the for loop), but I don't know how (if anyone does, please comment!). 您有可能直接以某种方式(而不是使用for循环)解开嵌套的字典,但我不知道如何(如果有人这样做,请发表评论!)。

If we assume that the keys may differ, we gotta add some stuff, but there are no nested structures so I think it is still quite simple. 如果我们假设键可能有所不同,就必须添加一些东西,但是没有嵌套结构,因此我认为它仍然很简单。 Assume for example that dict2 has a key/value pair {3: {'trait5': 435, 'trait7': 42}}. 例如,假设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}}

I make use of set operations to get the shared keys and then the keys only in dict1 and dict2. 我利用set操作获取共享密钥,然后仅获取dict1和dict2中的密钥。 For example, the intersection of {1,2,3} and {1,2} is {1,2}, and the set difference {1,2,3} - {1,2} = {3}. 例如,{1,2,3}和{1,2}的交集为{1,2},并且集差{1,2,3}-{1,2} = {3}。

I hope it's clear enough! 我希望它足够清楚!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM