按键合并字典列表,检查值 - 如果新则添加,如果不同则更新

Merge list of dictionaries by key, check for values - add if new, update if different

我试图摆脱具有相同键的重复字典(通过合并它们),但还需要跟踪它们包含的值。我有 2 个列表:

person_list_1 = [
    {"name": "John",
     "cars": [
                {"make": "Audi", "model_year": 2001},
                {"make": "BMW", "model_year": 2009}
            ]
    },
    {"name": "Mary",
     "cars": [
                {"make": "Mazda", "model_year": 2003}
            ]
    },
]

person_list_2 = [
    {"name": "John",
     "cars": [
                {"make": "Audi", "model_year": 2017},
                {"make": "Volkswagen", "model_year": 2008}
            ]
    },
    {"name": "Ben",
     "cars": [
                {"make": "Ford", "model_year": 1984}
            ]
    }
]

如您所见,其中两个具有相同的 name 键,但值有点不同。

我希望它最终看起来像这样:

updated_person_list = [
    {"name": "John",
     "cars": [
                {"make": "Audi", "model_year": 2017},
                {"make": "BMW", "model_year": 2009},
                {"make": "Volkswagen", "model_year": 2008},
            ]
    },
    {"name": "Mary",
     "cars": [
                {"make": "Mazda", "model_year": 2003},
            ]
    },
    {"name": "Ben",
     "cars": [
                {"make": "Ford", "model_year": 1984}
            ]
    },
]

即,在两个列表之间找到匹配的字典键并相应地说明它们 - 如果这样的汽车已经存在于“汽车”列表中但生产年份不同,请更新嵌套字典。

尝试了许多不同的解决方案,包括 collections.defaultdictitertools.chain 等,但其中 none 次尝试成功。 有人可以帮忙吗?

你应该遍历字典并在临时字典中累积项目,名称作为键,值作为汽车字典,从品牌到汽车字典,最后我们将这个字典转换为我们想要的字典:

def iterate(acc, l):
    for p in l:
        name = p["name"]
        if not name in acc:
            acc[name] = {}
        for c in p["cars"]:
            acc[name][c["make"]] = c

def merge(l1, l2):
    acc = {}
    iterate(acc, l1)
    iterate(acc, l2)
    return acc

def convert(acc):
    resp = []
    for k, v in acc.items():
        resp.append({"name": k, "cars": list(v.values())})
    return resp

我们可以将此函数用作:

print(convert(merge(person_list_1, person_list_2)))

结果将是:

[
    {'name': 'John', 'cars': [
        {'make': 'Audi', 'model_year': 2017},
        {'make': 'BMW', 'model_year': 2009},
        {'make': 'Volkswagen', 'model_year': 2008}]
     },
    {'name': 'Mary', 'cars': [
        {'make': 'Mazda', 'model_year': 2003}
    ]
    },
    {'name': 'Ben', 'cars': [
        {'make': 'Ford', 'model_year': 1984}
    ]
    }
]