简体   繁体   English

合并具有相同键的python中的两个dict

[英]merge two dict in python having the same key

i have the following two dicts as 我有以下两个词

dict1 = {'roll':{1:{'abc':100},2:{'abc':200},4:{'abc':900}},'no_roll':{}}

dict2 = {'roll':{1:{'cde':500},2:{'cde':600}},'no_roll':{4:{'cde':500}}}

and i would like to merge get a dict like, 我想合并得到一个像这样的字典,

final_dict = {'roll': {1: {'abc': 100,'cde': 500},2:{'abc': 200,'cde': 600},4:{'abc':900}},'no_roll': {4:{'cde':500}}}

I was able to do with multiple for loop and if conditions.How can I do that with a line or two of code? 我能够做多个for循环和条件。我怎么能用一行或两行代码呢?

A bad one-liner, derived from multiple for loop logic using side-effect will be. 从使用副作用的多个for循环逻辑派生的坏单行将是。

{v4.update(v3) for v1 in dict1.values() for v2 in dict2.values() for v3 in v1.values() for v4 in v2.values()}

The output will be. 输出将是。

print(dict2)
#{'roll': {1: {'cde': 500, 'abc': 200}, 2: {'cbd': 600, 'abc': 200}}, 
#'no_roll': {}}

As you can see, the code isn't very readable but does the job 正如您所看到的,代码不是很易读,但可以完成工作

Generic method 通用方法

To merge two dicts with nested dicts, you have to perform a tree traversal (eg DFS): 要将两个dicts与嵌套dicts合并,您必须执行树遍历(例如DFS):

>>> d1 = {'roll':{1:{'abc':100},2:{'abc':200},4:{'abc':900}},'no_roll':{}}
>>> d2 = {'roll':{1:{'cde':500},2:{'cde':600}},'no_roll':{4:{'cde':500}}}

>>> def merge(d1, d2):
...     d = {k: d1[k] for k in set(d1) - set(d2)}
...     d.update({k: d2[k] for k in set(d2) - set(d1)})
...     for k in set(d2) & set(d1):
...         assert isinstance(d1[k], dict) == isinstance(d2[k], dict), "inconsistent dicts"
...         if isinstance(d1[k], dict):
...              d[k] = merge(d1[k], d2[k])
...         else:
...             d[k] = d2[k] # keep only the second value, but we can keep a list if needed
...     return d
...
>>> merge(d1, d2)
{'roll': {4: {'abc': 900}, 1: {'abc': 100, 'cde': 500}, 2: {'abc': 200, 'cde': 600}}, 'no_roll': {4: {'cde': 500}}}
>>> merge(d1, {'roll':400})
Traceback (most recent call last):
...
AssertionError: inconsistent dicts

In your case 在你的情况下

If the keys of the terminal values ( 'abc' and 'cde' ) are never the same in dict1 and dict2 , you can drop some security checks and let the first two lines merge the innermost dicts: 如果终端值( 'abc''cde' )的键在dict1dict2中从不相同, dict1可以删除一些安全检查,并让前两行合并最里面的dicts:

>>> def merge2(d1, d2):
...     d = {k: d1[k] for k in set(d1) - set(d2)}
...     d.update({k: d2[k] for k in set(d2) - set(d1)})
...     for k in set(d2) & set(d1):
...         d[k] = merge(d1[k], d2[k])
...     return d
...
>>> merge2(d1, d2)
{'roll': {4: {'abc': 900}, 1: {'abc': 100, 'cde': 500}, 2: {'abc': 200, 'cde': 600}}, 'no_roll': {4: {'cde': 500}}}

If you want to perform this in two lines: 如果您想以两行执行此操作:

>>> merge3 = lambda d1, d2: {**{k: d1[k] for k in set(d1) - set(d2)}, **{k: d2[k] for k in set(d2) - set(d1)}, **{k: merge3(d1[k], d2[k]) for k in set(d2) & set(d1)}}
>>> merge3(d1, d2)
{'roll': {4: {'abc': 900}, 1: {'abc': 100, 'cde': 500}, 2: {'abc': 200, 'cde': 600}}, 'no_roll': {4: {'cde': 500}}}

And with Python 3.8, one line: 使用Python 3.8,一行:

>>> (merge4 := lambda d1, d2: {**{k: d1[k] for k in set(d1) - set(d2)}, **{k: d2[k] for k in set(d2) - set(d1)}, **{k: merge4(d1[k], d2[k]) for k in set(d2) & set(d1)}})(d1, d2)
{'roll': {4: {'abc': 900}, 1: {'abc': 100, 'cde': 500}, 2: {'abc': 200, 'cde': 600}}, 'no_roll': {4: {'cde': 500}}}

That was just for fun: do not use clever solutions when they are too clever . 这只是为了好玩:当他们太聪明时,不要使用聪明的解决方案。

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

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