[英]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"}}},
]
我几乎可以通过循环second
和first
来完成这一点,如下所示:
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
和乱序字典中的额外键(注意上面的first
和second
列表)。 输出:
{
"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.