在Python中合并字典

时间:2018-01-31 17:38:08

标签: python

我有一个字典列表,

input = [{"id":2, "color":"green"}, 
         {"id":3, "color":"red"}, 
         {"id":2, "gender":"male"}, 
         {"id":3, "food":"ice_cream"}, 
         {"id":1, "food":"fish"}]

和我的预期输出为

output =[{"id":1, "food":"fish"}, 
         {"id":2, "color":"green", "gender":"male"}, 
         {"id":3, "color":"red", "food":"ice_cream"}]

有几种比嵌套for循环更简单的方法吗?

2 个答案:

答案 0 :(得分:5)

您不需要嵌套循环,只需一个简单的for循环即可:

>>> from collections import defaultdict
>>> output = defaultdict(dict)
>>> for d in input_:
...     output[d['id']].update(d)
...     
>>> output.values()
dict_values([{'id': 2, 'color': 'green', 'gender': 'male'}, {'id': 3, 'color': 'red', 'food': 'ice_cream'}, {'id': 1, 'food': 'fish'}])

现在您可以按id对输出值进行排序。

>>> [output[k] for k in sorted(output)]
[{'food': 'fish', 'id': 1},
 {'color': 'green', 'gender': 'male', 'id': 2},
 {'color': 'red', 'food': 'ice_cream', 'id': 3}]

如果数据很大,并且你想避免最后的O(n log n)排序步骤,你可以预先迭代输入以找到id列表,并保持线性复杂性(这类似于a radix sort)。

如果你坚持使用groupby(效率较低且可读性较差),你可以比接受的答案中的怪物更清洁。试试这个:

from itertools import groupby
from operator import itemgetter
from collections import ChainMap
k = itemgetter('id')
output = [dict(ChainMap(*group)) for _, group in groupby(sorted(input_, key=k), k)]

答案 1 :(得分:0)

虽然@ wim的解决方案是最干净的,但另一种可能性是使用itertools.groupby

import itertools
import functools
input = [{"id":2, "color":"green"}, {"id":3, "color":"red"}, {"id":2, "gender":"male"}, {"id":3, "food":"ice_cream"}, {"id":1, "food":"fish"}]
new_input = [functools.reduce(lambda x, y:{**x, **y}, list(b)) for _, b in itertools.groupby(sorted(input, key=lambda x:x['id']), key=lambda x:x['id'])]

输出:

[{'id': 1, 'food': 'fish'}, {'id': 2, 'color': 'green', 'gender': 'male'}, {'id': 3, 'color': 'red', 'food': 'ice_cream'}]
相关问题