将不同数量的字典与嵌套字典中的不同键合并的通用函数

Generalized function to merge different number of dictionaries with different keys in nested dictionaries

我想制作一个通用函数,以在 python 中的嵌套词典中合并不同数量的具有不同键的嵌套词典。但是,如果我们在嵌套字典中有相同的键,下面这个函数就可以正常工作:

data = [dict1, dict2, dict3]

result = {k: {ik: [] for ik in dict1[k].keys()} for k in dict1.keys()}

for entry in data:
  for key, value in entry.items():
    for inner_key, inner_value in value.items():
        result[key][inner_key].append(inner_value)

我的输入字典是:

dict1 = {"canada":{'america':189,'asia':175,'europe': 186},
     "norway":{'australia': 123,'africa':124,'brazil':125}}
dict2=  {"canada":{'florida':13,'asia':14,'europe': 15},
     "norway":{'california': 17,'africa':18,'brazil':19}}
dict3=  {"canada":{'africa':127,'asia':256,'europe': 16, 'brazil':15},
     "norway":{'australia': 17,'africa':18,'brazil':19}}
# Expected Output
{'canada': {'africa': 127,
'america': 189,
'asia': [175, 14, 256],
'brazil': 15,
'europe': [186, 15, 16],
'florida': 13},
'norway': {'africa': [124, 18, 18],
'australia': 123,
'brazil': [125, 19, 19],
'california': 17}}

一种选择是使用 dict.setdefault 更新内部字典。

out = {}
for k in dict1.keys() | dict2.keys() | dict3.keys():
    inner = {}
    for d in [dict1, dict2, dict3]:
        for i,j in d.get(k, {}).items():
            inner.setdefault(i, []).append(j)
    out[k] = inner

如果字典中的其他键都相同,我们可以稍微简化一下。

此外,如果您坚持为单例列表使用整数(而不是列表),您可以尝试以下操作(但我认为混合数据类型不是一个好主意,因为之后您需要检查是否值为 int 或 list):

def merge_dicts(dicts):
    out = {}
    for k in dicts[0]:
        inner = {}
        for d in dicts:
            for i,j in d.get(k, {}).items():
                if i in inner and isinstance(inner[i], list):
                    inner[i].append(j)
                elif i in inner:
                    inner[i] = [inner[i], j]
                else:
                    inner[i] = j
        out[k] = inner
    return out

输出:

>>> out = merge_dicts([dict1,dict2,dict3])
{'canada': {'america': 189,
  'asia': [175, 14, 256],
  'europe': [186, 15, 16],
  'florida': 13,
  'africa': 127,
  'brazil': 15},
 'norway': {'australia': [123, 17],
  'africa': [124, 18, 18],
  'brazil': [125, 19, 19],
  'california': 17}}