non ottiene più semplice di questo, penso:
a=[("13.5",100)]
b=[("14.5",100), ("15.5", 100)]
c=[("15.5",100), ("16.5", 100)]
input=[a,b,c]
from collections import Counter
print sum(
(Counter(dict(x)) for x in input),
Counter())
noti che Counter
(noto anche come un multiset) è la struttura dei dati più naturale per i vostri dati (un tipo di set a cui elementi possono appartenere più di una volta, o equivalentemente - una mappa con semantica Elemento -> Ricorrenza. Potresti averlo usato in primo luogo, invece di liste di tuple.
anche possibile:
from collections import Counter
from operator import add
print reduce(add, (Counter(dict(x)) for x in input))
utilizzando reduce(add, seq)
anziché sum(seq, initialValue)
è generalmente più flessibile e consente di saltare passando il valore iniziale ridondante.
Si noti che è anche possibile utilizzare operator.and_
per trovare l'intersezione dei multiset anziché la somma.
La variante precedente è terribilmente lenta, perché un nuovo contatore viene creato ad ogni passaggio. Risolviamolo.
Sappiamo che Counter+Counter
restituisce un nuovo Counter
con dati uniti.Questo è OK, ma vogliamo evitare la creazione extra. Usiamo Counter.update
invece:
aggiornamento (self, iterable = None, ** kwds) Metodo collections.Counter non legato
Come dict.update(), ma aggiungere conta invece di sostituirli. L'origine può essere un iterabile, un dizionario o un'altra istanza Counter.
Questo è quello che vogliamo. Prendiamolo con una funzione compatibile con reduce
e vediamo cosa succede.
def updateInPlace(a,b):
a.update(b)
return a
print reduce(updateInPlace, (Counter(dict(x)) for x in input))
Questo è solo leggermente più lento della soluzione dell'OP.
Benchmark: http://ideone.com/7IzSx(Aggiornato con un'altra soluzione, grazie alla astynax)
(anche: Se si desidera disperatamente un one-liner, è possibile sostituire updateInPlace
di lambda x,y: x.update(y) or x
che funziona il allo stesso modo e si dimostra anche essere una frazione di secondo più veloce, ma non riesce a leggibilità.Non :-))
uso 'Counter()' –
@AshwiniChaudhary: 'contatore()' solo conta le occorrenze e, poiché i valori sono già pre-compilati, non funzionerà per questo scenario. –
@ChristianWitts vedere la mia soluzione di seguito. –