简体   繁体   English

合并具有公共键/值对的两个字典的大多数 Pythonic 方法

[英]Most Pythonic way to merge two dictionnaries having common key/value pair

I have two lists of python dictionnaries:我有两个 python 词典列表:

l1 = [{"id":1, "name":"A"}, {"id":2, "name":"B"}]
l2 = [{"id":1, "full_name":"Alfred"}, {"id":2, "full_name":"Barbara"}]

My goal is to have a list as follow:我的目标是有一个列表如下:

l3 = [{"id":1, "full_name":"Alfred", "name":"A"}, {"id":2, "full_name":"Barbara", "name":"B"}]

I think I could use nested loops to do this, but I'm sure it should be possible to do it in a better and more pythonic way.我想我可以使用嵌套循环来做到这一点,但我确信应该可以用更好、更 pythonic 的方式来做到这一点。

from collections import defaultdict


res = defaultdict(dict)
for a, b in zip(l1, l2):
    key1 = a['id']
    key2 = b['id']
    res[key1].update(a)
    res[key2].update(b)

print(list(res.values())) # [{'id': 1, 'name': 'A', 'full_name': 'Alfred'}, {'id': 2, 'name': 'B', 'full_name': 'Barbara'}]

Although this would work in a single iteration you might want to simplify your underlying data structures a bit to make them easier to work with.尽管这可以在单次迭代中工作,但您可能希望稍微简化底层数据结构,使它们更易于使用。

In one line (assuming id fields have perfect 1:1 mapping):在一行中(假设 id 字段具有完美的 1:1 映射):

result = [x | y for x, y in zip(sorted(l1, key = lambda x: x['id']), sorted(l2, key = lambda x: x['id']) )]

Assuming you sort the lists by the ID value in advance and that the ID values in the two lists are the same (just possibly in a different order), we can do it with a simple zip call.假设您预先按 ID 值对列表进行sort ,并且两个列表中的 ID 值相同(只是顺序可能不同),我们可以通过简单的zip调用来完成。

l1.sort(key=lambda x: x["id"])
l2.sort(key=lambda x: x["id"])

def merge(x, y):
    a = {}
    a.update(x)
    a.update(y)
    return a

l3 = [merge(x, y) for x, y in zip(l1, l2)]

Note that in Python 3.9 and newer, merge is simply |请注意,在 Python 3.9 及更新版本中, merge只是| , so we can write , 所以我们可以写

l3 = [x | y for x, y in zip(l1, l2)]

and eliminate the need for the helper function altogether.并完全消除对助手 function 的需要。

I'd suggest restructuring your input data when creating it, so that id is an actual identifier for each specific person.我建议在创建输入数据时重组您的输入数据,以便id是每个特定人的实际标识符。 If you make value of id key for an outer dictionary, you can do it in a single pass through one each of the mappings.如果您为外部字典设置id键的值,则可以通过每个映射一次完成。

from collections import defaultdict
l1 = {1:{"name":"A"}, 2:{"name":"B"}, 3:{"name":"C"}}
l2 = {1:{"full_name":"Alfred"}, 2:{"full_name":"Barbara"}}

result = defaultdict(dict)

for li in [l1, l2]:
    for k,v in li.items():
        result[k].update(v)

print(result)

(I removed the "id":value from the data because it's redundant with this form of data but adding it back in should be no problem if you really need it there.) (我从数据中删除了"id":value ,因为它对于这种形式的数据是多余的,但如果你真的需要它,将它重新添加进去应该没有问题。)


l1 = [{"id":1, "name":"A"}, {"id":2, "name":"B"}]
l2 = [{"id":1, "full_name":"Alfred"}, {"id":2, "full_name":"Barbara"}]


print([{**i,**j} for i in l1 for j in l2 if i["id"] ==j["id"]])

Result:结果:

[{'id': 1, 'name': 'A', 'full_name': 'Alfred'}, {'id': 2, 'name': 'B', 'full_name': 'Barbara'}]

you could try something like this, which you maybe already knew... would be interesting to see something more pythonic:)你可以尝试这样的事情,你可能已经知道了......看到更多pythonic的东西会很有趣:)

Use the id as identifer, create new dicts and update them - more comments in code.使用 id 作为标识符,创建新的字典并更新它们——代码中有更多注释。

No sorting needed, un"even" source lists inner dicts will be kept as well不需要排序,不“均匀”的源列表内部字典也将被保留

l1 = [{"id":1, "name":"A"}, {"id":2, "name":"B"}]
l2 = [{"id":1, "full_name":"Alfred"}, {"id":2, "full_name":"Barbara"}]

# intermediate dictionary that keeps all collected inner dicts at the id
d = {}
# go through both lists
for inner_d in l1 + l2:
    # create a new empty dict under the id if needed 
    what = d.setdefault(inner_d["id"], {})
    # add all things from the inner dict
    what.update(inner_d.items())

as_list = list(d.values())
print(as_list)

Output: Output:

[{'id': 1, 'name': 'A', 'full_name': 'Alfred'}, 
 {'id': 2, 'name': 'B', 'full_name': 'Barbara'}]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM