簡體   English   中英

Python 合並兩個字典列表,其中字典鍵匹配

[英]Python merge two lists of dicts, where dict key matches

我有兩個列表,每個列表包含約 100 個字典。 此處顯示了一個虛擬插圖:

first = [
    {"ip-10-1-1-1": {"job": {"company": "IBM", "title": "engineer"}}},
    {"ip-10-1-1-20": {"job": {"company": "Dell", "title": "manager"}}},
    {"ip-10-1-1-35": {"job": {"company": "Apple", "title": "CEO"}}},
]

second = [
    {"ip-10-1-1-1": {"demographics": {"age": 30, "gender": "female"}}},
    {"ip-10-1-1-20": {"demographics": {"age": "30", "gender": "male"}}},
    {"ip-10-1-1-49": {"demographics": {"age": "32", "gender": "female"}}},
]

我正在嘗試將這些與此結果合並:

[
    {
        "ip-10-1-1-1": {
            "demographics": {"age": 30, "gender": "female"},
            "job": {"company": "IBM", "title": "engineer"},
        }
    },
    {
        "ip-10-1-1-20": {
            "demographics": {"age": "30", "gender": "male"},
            "job": {"company": "Dell", "title": "manager"},
        }
    },
    {"ip-10-1-1-35": {"job": {"company": "Apple", "title": "CEO"}}},
    {"ip-10-1-1-49": {"demographics": {"age": "32", "gender": "female"}}},
]


我幾乎可以通過循環secondfirst來完成這一點,如下所示:

merged = []
for d1 in second:
    for k1 in d1.keys():
        for d2 in first:
            for k2 in d2.keys():
                if k2 == k1:
                    d1[k1]["job"] = d2[k2]["job"]
    merged.append(d1)
print(merged)

我是 python 的新手,但是我希望/認為必須有一種更 Python 的方式來做到這一點。

編輯:為了使事情更復雜 - 我可以在first但不是second有鑰匙,反之亦然。 我已經更新了示例以反映這一點。

這是一個可能的單行解決方案:

result = {f'user_{i + 1}': dict(**d1[f'user_{i + 1}'], **d2[f'user_{i + 1}'])
          for i, (d1, d2) in enumerate(zip(first, second))}

如果您使用的是 python >=3.8 那么您可以在字典理解中使用賦值:

result = {(key := f'user_{i + 1}'): dict(**d1[key], **d2[key])
          for i, (d1, d2) in enumerate(zip(first, second))}
first = [
    {"user_1": {"job": {"company": "IBM", "title": "engineer"}}},
    {"user_2": {"job": {"company": "Dell", "title": "manager"}}},
    {"user_3": {"job": {"company": "Microsoft", "title": "manager"}}},
]
second = [
    {"user_2": {"demographics": {"age": "30", "gender": "male"}}},
    {"user_1": {"demographics": {"age": "30", "gender": "female"}}},
]


def merge_list_of_dicts(list_of_dicts, current={}):
    get_key = lambda d: next(iter(d))
    get_value = lambda d: next(iter(d.values()))

    for d in list_of_dicts:
        key = get_key(d)
        value = get_value(d)

        if key not in current:
            current[key] = value
        else:
            current[key].update(value)

    return current


output = merge_list_of_dicts(second, merge_list_of_dicts(first))
print(output)

將處理first和亂序字典中的額外鍵(注意上面的firstsecond列表)。 輸出:

{
    "user_1": {
        "job": {"company": "IBM", "title": "engineer"},
        "demographics": {"age": "30", "gender": "female"},
    },
    "user_2": {
        "job": {"company": "Dell", "title": "manager"},
        "demographics": {"age": "30", "gender": "male"},
    },
    "user_3": {"job": {"company": "Microsoft", "title": "manager"}},
}

如果您想要更清潔的 API:

def merge_list_of_dicts(d1: dict, d2: dict):
    def merge(list_of_dicts, current={}):
        get_key = lambda d: next(iter(d))
        get_value = lambda d: next(iter(d.values()))

        for d in list_of_dicts:
            key = get_key(d)
            value = get_value(d)

            if key not in current:
                current[key] = value
            else:
                current[key].update(value)

        return current
    return merge(d2, merge(d1))


output = merge_list_of_dicts(first, second)
import itertools

final_list = []
for key, group in itertools.groupby(
    sorted(first + second, key=lambda x: tuple(x)[0]), key=lambda x: tuple(x)[0]
):
    temp = {key: {}}
    for d in group:
        _, value = tuple(*d.items())
        temp[key].update(value)
    final_list.append(temp)
print(final_list)

Output:

[{'ip-10-1-1-1': {'job': {'company': 'IBM', 'title': 'engineer'}, 'demographics': {'age': 30, 'gender': 'female'}}}, {'ip-10-1-1-20': {'job': {'company': 'Dell', 'title': 'manager'}, 'demographics': {'age': '30', 'gender': 'male'}}}, {'ip-10-1-1-35': {'job': {'company': 'Apple', 'title': 'CEO'}}}, {'ip-10-1-1-49': {'demographics': {'age': '32', 'gender': 'female'}}}]

暫無
暫無

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

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