2013-01-06 15 views
20

Ho una lista di tuple simile a questo:somma ogni valore in una lista di tuple

l = [(1, 2), (3, 4), (5, 6), (7, 8), (9, 0)] 

Voglio creare un semplice one-liner che mi darà il seguente risultato:

r = (25, 20) or r = [25, 20] # don't care if tuple or list. 

che sarebbe come fare il seguente:

r = [0, 0] 
for t in l: 
    r[0]+=t[0] 
    r[1]+=t[1] 

sono sicuro che è qualcosa di molto semplice, ma non riesco a pensare di esso.

Nota: ho guardato domande simili già:

How do I sum the first value in a set of lists within a tuple?

How do I sum the first value in each tuple in a list of tuples in Python?

+0

possibile du plicate di [Python element-wise tuple operations come sum] (http://stackoverflow.com/questions/497885/python-element-wise-tuple-operations-like-sum) –

+0

@CiroSantilli: non è un duplicato. La domanda che hai collegato funziona con * due * tuple. Questa domanda su un * elenco * di tuple. La trasposizione è la parte essenziale della soluzione. Sebbene le risposte funzionino quasi alla lettera in entrambi i casi. Ancora tuple 'a, b' e' a_list_of_tuples' sono differenti (la differenza potrebbe essere esposta in quale soluzione è la più efficiente). – jfs

risposta

46

Usa zip() e sum():

In [1]: l = [(1, 2), (3, 4), (5, 6), (7, 8), (9, 0)] 

In [2]: [sum(x) for x in zip(*l)] 
Out[2]: [25, 20] 

o:

In [4]: map(sum, zip(*l)) 
Out[4]: [25, 20] 

timeit risultati:

In [16]: l = [(1, 2), (3, 4), (5, 6), (7, 8), (9, 0)]*1000 

In [17]: %timeit [sum(x) for x in zip(*l)] 
1000 loops, best of 3: 1.46 ms per loop 

In [18]: %timeit [sum(x) for x in izip(*l)]  #prefer itertools.izip 
1000 loops, best of 3: 1.28 ms per loop 

In [19]: %timeit map(sum, zip(*l)) 
100 loops, best of 3: 1.48 ms per loop 

In [20]: %timeit map(sum, izip(*l))    #prefer itertools.izip 
1000 loops, best of 3: 1.29 ms per loop 
+0

O_O non riesco a credere a quanto sia stato semplice, come potrei aver dimenticato 'zip'? Grazie. Quale è più efficiente? il metodo 'map' o' list-comprehension'? –

+0

@Inbar test e scoprire. – Triptych

+1

'map' talvolta supera la' list comprehension' quando viene usata con le funzioni built-in. –

2

voglio aggiungere qualcosa alla risposta data:

Se ho un array di dict esempio

l = [{'quantity': 10, 'price': 5},{'quantity': 6, 'price': 15},{'quantity': 2, 'price': 3},{'quantity': 100, 'price': 2}] 

e voglio ottenere due (o più) somme di quantità calcolate sui valori, ad es. somma delle quantità e del prezzo quantità *

posso fare:

(total_quantity, total_price) = (
sum(x) for x in zip(*((item['quantity'], 
         item['price'] * item['quantity']) 
         for item in l))) 

Invece di:

total_quantity = 0 
total_price = 0 
for item in l: 
    total_quantity += item['quantity'] 
    total_price += item['price'] * item['quantity'] 

Forse la prima soluzione è meno leggibile, ma è più "Pythonesque" :)

+1

Cosa aggiunge alla risposta di Ashwini? La domanda non riguarda un elenco di dict –

+1

hai ragione, ma aggiunge qualcosa sull'utilizzo di sum e zip per operazioni complesse. Stavo cercando qualcosa del genere, ho trovato questa risposta e l'ho usata per il mio problema, che riguardava le dicts. Così ho pensato che sarebbe stato bello condividere la mia soluzione con qualcun altro che potrebbe avere il mio stesso problema. –

1

Senza usare zip

sum(e[0] for e in l), sum(e[1] for e in l) 
Problemi correlati