簡體   English   中英

如何合並嵌套字典?

[英]How to merge nested dictionaries?

我有一個嵌套字典列表(python 3.9),看起來像這樣:

records = [
    {'Total:': {'Owner:': {'Available:': {'15 to 34 years': 1242}}}},
    {'Total:': {'Owner:': {'Available:': {'35 to 64 years': 5699}}}},
    {'Total:': {'Owner:': {'Available:': {'65 years and over': 2098}}}},
    {'Total:': {'Owner:': {'No Service:': {'15 to 34 years': 43}}}},
    {'Total:': {'Owner:': {'No Service:': {'35 to 64 years': 64}}}},
    {'Total:': {'Owner:': {'No Service:': {'65 years and over': 5}}}},
    {'Total:': {'Renter:': {'Available:': {'15 to 34 years': 1403}}}},
    {'Total:': {'Renter:': {'Available:': {'35 to 64 years': 2059}}}},
    {'Total:': {'Renter:': {'Available:': {'65 years and over': 395}}}},
    {'Total:': {'Renter:': {'No Service:': {'15 to 34 years': 16}}}},
    {'Total:': {'Renter:': {'No Service:': {'35 to 64 years': 24}}}},
    {'Total:': {'Renter:': {'No Service:': {'65 years and over': 0}}}},
]

嵌套級別並不總是一致的。 上面的示例有 4 個級別(總、所有者/租用者、可用/無服務、年齡組),但有些示例只有一個級別,而其他示例則多達 5 個級別。

我想以一種不會像update(){*dict_a, **dict_b}那樣替換最終字典的方式合並數據。

最終的 output 應如下所示:

combined = {
    'Total': {
        'Owner': {
            'Available': {
                '15 to 34 years': 1242,
                '35 to 64 years': 5699,
                '65 years and over': 2098
            },
            'No Service:': {
                '15 to 34 years': 43,
                '35 to 64 years': 64,
                '65 years and over': 5
            }
        },
        'Renter': {
            'Available': {
                '15 to 34 years': 1403,
                '35 to 64 years': 2059,
                '65 years and over': 395
            },
            'No Service:': {
                '15 to 34 years': 16,
                '35 to 64 years': 24,
                '65 years and over': 0
            }
        },
    }
}

遞歸是一種在任意嵌套結構上導航和操作的簡單方法:

def combine_into(d: dict, combined: dict) -> None:
    for k, v in d.items():
        if isinstance(v, dict):
            combine_into(v, combined.setdefault(k, {}))
        else:
            combined[k] = v

combined = {}
for record in records:
    combine_into(record, combined)
print(combined)
{'Total:': {'Owner:': {'Available:': {'15 to 34 years': 1242, '35 to 64 years': 5699, '65 years and over': 2098}, 'No Service:': {'15 to 34 years': 43, '35 to 64 years': 64, '65 years and over': 5}}, 'Renter:': {'Available:': {'15 to 34 years': 1403, '35 to 64 years': 2059, '65 years and over': 395}, 'No Service:': {'15 to 34 years': 16, '35 to 64 years': 24, '65 years and over': 0}}}}

這里的一般想法是,對combine_into的每次調用都采用一個 dict 並將其組合到combined dict 中——每個本身就是 dict 的值都會導致另一個遞歸調用,而其他值只是按原樣復制到combined中。

請注意,如果某些records對特定節點是否為葉子存在分歧,這將引發異常(或破壞某些數據)!

對於這個特定的例子,一種更直接的組合方式。

out = {}
for dct1 in records:
    for k1, dct2 in dct1.items():
        for k2, dct3 in dct2.items():
            for k3, dct4 in dct3.items():
                out.setdefault(k1,{}).setdefault(k2,{}).setdefault(k3,{}).update(dct4)

將比遞歸 function 更快,但必須根據嵌套的深度進行更新。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM