2013-04-23 13 views
9

Mam listę słowników, które chciałbym połączyć w jeden słownik i dodać wartości z każdego słownika na liście. Na przykład:Najszybszy sposób łączenia n-słowników i dodawania wartości w 2.6

ds = [{1: 1, 2: 0, 3: 0}, {1: 2, 2: 1, 3: 0}, {1: 3, 2: 2, 3: 1, 4: 5}] 

Końcowe wyniki powinny być pojedynczym słownika:

merged = {1: 6, 2: 3, 3: 1, 4: 5} 

Jestem zainteresowany wydajności i szukam najszybszej realizacji, które można scalić listę N-słowników w jednym słownik i podsumuj wartości. Oczywistą implementacją jest:

from collections import defaultdict 

merged = defaultdict(int) 

for d in ds: 
    for k, v in d.items(): 
     merged[k] += v 

Czy jest to szybszy sposób w Pythonie 2.6?

+0

NVM to nie jest duplikatem ponieważ pozwala to jedynie 2,6 – jamylak

+0

lub http://stackoverflow.com/questions/3490738/how-to-sum-dict-elements – ShinTakezou

+0

@ user1728853 Jak duży będzie średni słownik? – jamylak

Odpowiedz

6

defaultdict jest nadal najszybszy, znalazłem kilka sposobów, aby ją przyspieszyć poprzez buforowanie nazw funkcji i teraz tylko znaleźć inny sposób, który pędził go znacznie, po prostu iteracja for k in d zamiast korzystania d.items() lub d.iteritems()

Niektóre czasy do tej pory:

from random import randrange 
ds = [dict((randrange(1, 1000), randrange(1, 1000)) for i in xrange(500)) 
     for i in xrange(10000)] 

# 10000 dictionaries of approx. length 500 

from collections import defaultdict 

def merge1(dicts, defaultdict=defaultdict, int=int): 
    merged = defaultdict(int) 
    for d in dicts: 
     for k in d: 
      merged[k] += d[k] 
    return merged 

def merge2(dicts): 
    merged = {} 
    merged_get = merged.get 
    for d in dicts: 
     for k in d: 
      merged[k] = merged_get(k, 0) + d[k] 
    return merged 


def merge3(dicts): 
    merged = {} 
    for d in dicts: 
     for k in d: 
      merged[k] = merged[k] + d[k] if k in merged else 0 
    return merged 


from timeit import timeit 
for func in ('merge1', 'merge2', 'merge3'): 
    print func, timeit(stmt='{0}(ds)'.format(func), 
         setup='from __main__ import merge1, merge2, merge3, ds', 
         number=1) 

merge1 0.992541510164 
merge2 1.40478747997 
merge3 1.23502204889 
+2

Czy jesteś pewien, że jest to rzeczywiście szybsze? (Pytam, ponieważ w przeszłości znalazłem zaskakująco powolne obiekty Counter). – DSM

+0

@DSM to nie ma znaczenia, że ​​to duplikat, myślę, że czasy są w drugim wątku – jamylak

+0

Powinienem wspomnieć, jestem na Pythonie 2.6 – user1728853

Powiązane problemy