2014-12-28 6 views
3

두 개의 키/값 쌍이있는 dicts 목록이 있습니다. 두 번째 키의 값을 합산하여 첫 번째 키와 동일한 값을 공유하는 사전을 결합해야합니다. 예를 들어 : 속성별로 객체 배열 집계

[ 
    {'foo': 34, 'bar': 5}, 
    {'foo': 35, 'bar': 10} 
] 

내가 작동하지만 끔찍 자세한 보인다 다음 함수를 썼다, 나는 것이 시원한 파이썬 트릭이 거의 확신 :로

[ 
    {'foo': 34, 'bar': 2}, 
    {'foo': 34, 'bar': 3}, 
    {'foo': 35, 'bar': 1}, 
    {'foo': 35, 'bar': 7}, 
    {'foo': 35, 'bar': 2} 
] 

가 나올 것입니다 청소기, 그리고 더 performant.

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 

누구든지 의견이 있으십니까? itertools.groupby를 사용

+1

[itertools.groupby] (https://docs.python.org/2/library/itertools.html#itertools.groupby) –

+0

시간 측정 테스트에서 falsetru의 답변이 30 % 이상 우수하기 때문에 fthethethe의 답변을 선택했습니다. 내 가능성이 배열 크기에. 나는 그 차이가 더 큰 배열에 대해서는 더 작을 수 있다고 생각한다. 흥미롭게도 원래 코드는 두 코드 사이에서 수행되었습니다. – domoarrigato

+0

@domoarrigato 'groupby'에 대한 입력이 'sorted'(O (lg N)) 여야하기 때문에 시차가 있다고 생각합니다. 하지만 내 사전 솔루션은 O (N)입니다. – thefourtheye

답변

3
  1. 그룹화 foo 값을 기준으로 bar 값을하고 추가합니다.

    >>> grouper = {} 
    >>> for d in data: 
    ...  grouper[d["foo"]] = grouper.get(d["foo"], 0) + d["bar"] 
    ... 
    >>> grouper 
    {34: 5, 35: 10} 
    
  2. 다음이

    >>> [{"foo": item, "bar": grouper[item]} for item in grouper] 
    [{'foo': 34, 'bar': 5}, {'foo': 35, 'bar': 10}] 
    
5

: 목록이 이미 정렬되어있는 경우

>>> 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}] 

, 당신은 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}] 
0
이 용액 collections.defaultdict 사용

같은 지능형리스트와 dicts 목록을 재구성 :

def combine(arr): 
    c = collections.defaultdict(int) 
    for i in arr: 
     c[i['foo']] += i['bar'] 
    # c == {34: 5, 35: 10} 

    return [{'foo': k, 'bar': c[k]} for k in sorted(c)] 

사전 c 것은 더불어 defaultdict 인 키로서의 'foo'의 값, 및 값으로서의 'bar'의 값.