[英]Python: Most efficient way to combine complex dictionaries
Let's say I have two dicts consisting of multi-leveled sets:假设我有两个由多级集组成的字典:
houses:
- house4:
- level1:
- unitA
- unitB
- level8:
- unitG
- house6:
- level5:
- unitK
and和
houses:
- house6:
- level4:
- unitT
- level5:
- unitK
- house3:
- level8:
- unitG
What is the most efficient way to combine them without duplicates?将它们组合起来而不重复的最有效方法是什么?
I can write a three level loop and generate a new dict by recombining each subset with set.union but that kind of doesn't look nice.我可以编写一个三层循环并通过将每个子集与 set.union 重新组合来生成一个新的 dict,但这看起来不太好。
a ={"house4": {
"level1": ["unitA", "unitB"],
"level8": ["unitG"],
},
"house6": {
"level6": ["unitK"]
}
}
b = {"house6": {
"level4": ["unitT"],
"level5": ["unitK"]
},
"house3": {
"level8": ["unitG"]
}
}
a.update(b)
keys in "a" are replaced by "b" ie "a" once updated will have the value of "house 6" from dictionary "b". “a”中的键被“b”替换,即“a”一旦更新将具有字典“b”中的“house 6”的值。 If you need to resolve duplicates at a lower level in your dictionary, make sure to post a question that demos exactly what you need--it's unclear.
如果您需要在字典中解决较低级别的重复项,请确保发布一个问题来演示您所需要的内容——目前还不清楚。
Assuming that your last level of these dictionaries are sets of strings, you could use nested loops:假设这些字典的最后一级是字符串集,您可以使用嵌套循环:
for k1,v1 in b.items(): # e.g. 'houses': {...
d1 = a.setdefault(k1,dict())
for k2,v2 in v1.items(): # e.g. 'house6': {...
d2 = d1.setdefault(k2,dict())
for k3,v3 in v2.items(): # e.g. 'level4': {'unitT'}
d2.setdefault(k3,list()).update(v3)
Note that the sub-dictionaries added to a
are new instances (not references to the ones in b
. So if the content of the b
structure is changed afterward, you won't get undesirable side effect in the a
structure.请注意,添加到
a
的子词典是新实例(不是对b
中的那些的引用。因此,如果b
结构的内容随后发生更改,您将不会在a
结构中获得不良的副作用。
If the number of levels in the dictionaries is unknown, you can define a recursive function that does the same thing for any number of levels:如果字典中的级别数未知,您可以定义一个递归 function 对任意数量的级别执行相同的操作:
def merge(a,b):
if isinstance(a,dict):
for k,v in b.items(): merge(a.setdefault(k,type(v)()),v)
elif isinstance(a,set): a.update(b)
elif isinstance(a,list): a.extend(b)
Assuming the units are sets, you can do it with 2 for-loops.假设单位是集合,您可以使用 2 个 for 循环来完成。
Iterate over b
and check if a house in it exists in a
, if not just add it to a
.遍历
b
并检查其中的房子是否存在于a
中,如果不只是将其添加到a
中。 If it is, then iterate over the levels in that house and check if a level in it exists in the same house in a
.如果是,则遍历该房屋中的关卡并检查其中的关卡是否存在于
a
中的同一房屋中。 If there is, then add these new units to the existing level in a
, if not add this level to the same house in a
:如果有,则将这些新单元添加到
a
中的现有级别,如果没有将此级别添加到a
中的同一房屋:
for house, levels in b.items():
if house in a:
for level, units in levels.items():
if level in a[house]:
a[house][level].update(units)
else:
a[house][level] = units
else:
a[house] = levels
The same can be constructed using dict.setdefault
as well:同样可以使用
dict.setdefault
构造:
for house, levels in b.items():
a.setdefault(house, dict())
for level, units in levels.items():
a[house].setdefault(level, set()).update(units)
print(a)
Output: Output:
{'house4': {'level1': {'unitA', 'unitB'}, 'level8': ['unitG']},
'house6': {'level6': {'unitK'}, 'level4': {'unitT'}, 'level5': {'unitK'}},
'house3': {'level8': {'unitG'}}}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.