合并具有列表初始化的字典列表

3

我的当前列表:

my_list = [
   {'id': 1, 'val': [6]},
   {'id': 2, 'val': [7]},
   {'id': 3, 'val': [8]},
   {'id': 2, 'val': [9]},
   {'id': 1, 'val': [10]},
]

期望输出:

my_list = [
   {'id': 1, 'val': [6, 10]},
   {'id': 2, 'val': [7, 9]},
   {'id': 3, 'val': [8]},
]

我尝试过以下几点:

    my_new_list = []
    id_set = set()

    for d in my_list:
        if d['id'] not in id_set:
            id_set.add(d['id'])
            temp = {'id': d['id'], 'val': d['val']}
            my_new_list.append(temp)
        else:
             # loop over the new list and find the dict which already have d['id'] and update by appending value
             # but this is not efficient

有没有更高效的方法或者我不知道的一些内置函数。

提示:顺序很重要!


由于新列表中的id值是唯一的,您可以使用字典来代替列表,并以id作为键。这样,您就不必循环遍历新列表,而是可以直接通过id访问它。 - spectras
输出列表的顺序重要吗? - user2390182
@schwobaseggl:是的,顺序很重要,这就是为什么我没有像y spectras提到的那样使用字典的原因。 - Wendy
3个回答

4

.setdefault()是你的好朋友:

(我们应该使用collections.OrderedDict来记住首次插入键的顺序。)

>>> import collections

>>> result = collections.OrderedDict()
>>> for d in my_list:
...     result.setdefault(d["id"], []).extend(d["val"])

>>> lst = []
>>> for k, v in result.items():
...     lst.append({"id": k, "val": v})

第二部分的列表推导式也非常易读:lst = [{"id": k, "val": v} for k, v in result.items()] - spectras

1

ozgur 相同的方法,但使用 collections.defaultdict

>>> from collections import defaultdict
>>> d = defaultdict(list)
>>> for dd in my_list:
        d[dd['id']].extend(dd['val'])
>>> d
defaultdict(<type 'list'>, {1: [6, 10], 2: [7, 9], 3: [8]})
>>>
>>> lst = []
>>> for k,v in d.iteritems():
        lst.append({'id':k, 'val':v})

>>> lst
[{'id': 1, 'val': [6, 10]}, {'id': 2, 'val': [7, 9]}, {'id': 3, 'val': [8]}]
>>>

重要的是顺序,我们能否使用OrderedDict而不是defaultdict来实现它。 - Wendy
如果按照你原来的 my_list,那么它会按顺序迭代,因此保持顺序不变。 - Iron Fist

0

您可以使用 itertools.groupby 来按 'id' 排序和分组原始的 list,并累加每个组的 'val'

from itertools import groupby

key_fnc = lambda d: d['id']
result = [
    {'id': k, 'val': sum([d['val'] for d in g], [])} 
        for k, g in groupby(sorted(my_list, key=key_fnc), key=key_fnc)
]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接