按属性聚合对象数组

dom*_*ato 3 python dictionary list

我有一个dicts列表,每个都有两个键/值对.我需要通过对第二个键的值进行求和来组合第一个键共享相同值的词组.例如:

[
    {'foo': 34, 'bar': 2}, 
    {'foo': 34, 'bar': 3}, 
    {'foo': 35, 'bar': 1}, 
    {'foo': 35, 'bar': 7}, 
    {'foo': 35, 'bar': 2}
]
Run Code Online (Sandbox Code Playgroud)

会出来的:

[
    {'foo': 34, 'bar': 5}, 
    {'foo': 35, 'bar': 10}
]
Run Code Online (Sandbox Code Playgroud)

我编写了以下函数,它可以工作,但看起来非常冗长,我几乎可以肯定有一个很酷的pythonic技巧,它会更干净,性能更高.

def combine(arr):
    arr_out = []
    if arr:
        arr_out.append({'foo': arr[0]['foo'], 'bar': 0})
        for i in range(len(arr)):
            if arr[i]['foo'] == arr_out[-1]['foo']:
                arr_out[-1]['bar'] += arr[i]['bar']
            else:
                arr_out.append({'foo': arr[i]['foo'], 'bar': arr[i]['bar']})
    return arr_out
Run Code Online (Sandbox Code Playgroud)

有人有什么建议吗?

fal*_*tru 5

使用itertools.groupby:

>>> arr = [
...     {'foo': 34, 'bar': 2},
...     {'foo': 34, 'bar': 3},
...     {'foo': 35, 'bar': 1},
...     {'foo': 35, 'bar': 7},
...     {'foo': 35, 'bar': 2}
... ]
>>> import itertools
>>> key = lambda d: d['foo']
>>> [{'foo': key, 'bar': sum(d['bar'] for d in grp)}
...  for key, grp in itertools.groupby(sorted(arr, key=key), key=key)]
[{'foo': 34, 'bar': 5}, {'foo': 35, 'bar': 10}]
Run Code Online (Sandbox Code Playgroud)

如果列表已经排序,您可以省略sorted调用:

>>> [{'foo': key, 'bar': sum(d['bar'] for d in grp)}
...  for key, grp in itertools.groupby(arr, key=key)]
[{'foo': 34, 'bar': 5}, {'foo': 35, 'bar': 10}]
Run Code Online (Sandbox Code Playgroud)