基于单一非唯一键合并两个字典列表
我有两个字典列表,比如:
l1 = [{"customer":"amy", "order":2}, {"customer":"amy", "order":3}, {"customer":"basil", "order":4}]
l2 = [{"customer":"amy", "died":"who fell down the stairs"}, {"customer":'basil', "died":"assaulted by bears"}]
我想找个优雅的方法,把第二个列表(l2)里的键放到第一个列表(l1)里。这是为了把使用不同值作为索引的字典列表合并在一起。
这个函数应该像这样:join(l1, l2, 'customer'),然后生成
l3 = [{"customer":"amy", "order":2,"died":"who fell down the stairs"}, {"customer":"amy", "order":3,"died":"who fell down the stairs"}, {"customer":"basil", "order":4,"died":"assaulted by bears"}}]
l3应该为l1中的每个字典都生成一个字典。
如果l1和l2在非连接键上有相同的值但不同的内容,l2的值会优先。
l2会有连接键的唯一值。
现在我试过这段不太好看的代码:
l3 = []
rdict = {}
for i in range(len(l2)):
rdict[l2[i][field]]=i
for d in l1:
l3.append(dict(d.items()+l2[rdict[d[field]]].items()))
return l3
还有 这个SO问题的解决方案,但那个假设所有列表中只有一个索引。
谢谢
3 个回答
0
l3= [{"id": 64, "attribute1": 2},
{"id": 62, "attribute1": 3},
{"id": 64, "attribute2": 3}]
l4 = [{"id": 64, "Energy1": 2},
{"id": 62, "Energy1": 3},
{"id": 64, "Energy2": 3}]
def m1(l1,l2):
l1d = {}
for dct in l1: l1d.setdefault(dct["id"], {}).update(dct)
l2d = {}
for dct in l2: l2d.setdefault(dct["id"], {}).update(dct)
aa = {
k : dict(l1d.get(k,{}),**v) for k,v in l2d.items()
}
aal = [*aa.values()]
aalp = print(aal)
return aalp
m1(l3, l4)
"""
Output :
[{'id': 64, 'attribute1': 2, 'attribute2': 3, 'Energy1': 2, 'Energy2': 3}, {'id': 62, 'attribute1': 3, 'Energy1': 3}]
"""
解释:
这段代码接收两个字典列表,然后把它们合并成一个字典列表。
代码首先从这两个字典列表中创建两个字典。
这些字典是通过把id当作键,其他的内容当作值来创建的。
接着,代码用id作为键,合并后的字典作为值,创建一个新的字典。
然后,代码从这个新字典中生成一个列表。
接下来,代码打印出这个列表。
最后,代码返回这个列表。
最好的方法是使用defaultdict(dict)
方法2(最佳):
from _collections import defaultdict
from operator import itemgetter
l1 = [{"id":1, "b":2},
{"id":2, "b":3},
{"id":3, "b":"10"},
{"id":4, "b":"7"}]
l2 = [{"id":1, "c":4},
{"id":2, "c":5},
{"id":6, "c":8},
{"id":7, "c":9}]
def m2(l1,l2):
d = defaultdict(dict)
for l in (l1,l2):
for innerdict in l :
d[innerdict['id']].update(innerdict)
dv = d.values()
dvsorted = sorted(d.values(),key= itemgetter('id'))
dvsorted1 = [*dvsorted]
dvsorted1_print = print(dvsorted1)
return dvsorted1_print
m2(l1, l2)
"""
Output :
[{'id': 1, 'b': 2, 'c': 4}, {'id': 2, 'b': 3, 'c': 5}, {'id': 3, 'b': '10'}, {'id': 4, 'b': '7'}, {'id': 6, 'c': 8}, {'id': 7, 'c': 9}]
"""
解释:
这段代码接收两个字典列表作为输入,并返回一个字典列表。
代码使用defaultdict来创建一个字典的字典。
代码使用update来更新内部的字典。
代码使用itemgetter来对字典列表进行排序。
代码使用*来解包字典列表。
打印出字典列表。
1
另一种答案...
def diff(d1, d2, key):
if d1[key] != d2[key]:
return d1
new_keys = list(set(d2) - set(d1))
for new_key in new_keys:
d1[new_key] = d2[new_key]
return d1
def join(l1, l2, key):
l3 = l1
for d2 in l2:
l3 = map(lambda d1: diff(d1, d2, key), l3)
return l3
3
简单:
SELECT *
FROM l1, l2
WHERE l1.customer = l2.customer
...开个玩笑...
def join(t1,t2,column):
result = []
for entry in t2:
for match in [d for d in t1 if d[column] == entry[column]]:
result.append(dict((k,v) for k,v in entry.items()+match.items()))
return result