我有一个字典列表,
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循环更简单的方法吗?
答案 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'}]