2013-05-14 1 views
5

Mi stavo chiedendo se esistesse un modo particolarmente pitioso di aggiungere due tuple elementwise?Aggiunta di due tuple elementwise

Finora (a e b sono tuple), ho

map(sum, zip(a, b)) 

mio risultato atteso sarebbe:

(a[0] + b[0], a[1] + b[1], ...) 

E una possibile pesare potrebbe essere quella di dare un peso e b 0.5 0.5 peso, o così via. (Sto cercando di prendere una media ponderata).

Che funziona bene, ma dire che volevo aggiungere una ponderazione, non sono abbastanza sicuro di come lo farei.

Grazie

+0

Qual è il tuo risultato previsto, allora? – msvalkon

+1

Si * stanno * elaborando l'elemento tuple 'a' e' b' saggio. Puoi anche fare 'tupla (somma (aa, bb) per aa, bb in zip (a, b))' per decomprimere i due elementi in variabili separate. Quale sarebbe la tua formula di ponderazione? –

+0

E invece di solo 'sum (i)' (o 'sum (aa, bb)' per quella questione), puoi usare un'espressione * diversa * per creare altri elementi. Includere una tupla con la somma e altri valori: '(somma (aa, bb), aa/bb)' per esempio. –

risposta

13

Zip poi riassumere ogni tupla.

[sum(x) for x in zip(a,b)] 

EDIT: Ecco una migliore, anche se la versione più complessa che permette di ponderazione.

from itertools import starmap, islice, izip 

a = [1, 2, 3] 
b = [3, 4, 5] 
w = [0.5, 1.5] # weights => a*0.5 + b*1.5 

products = [m for m in starmap(lambda i,j:i*j, [y for x in zip(a,b) for y in zip(x,w)])] 

sums = [sum(x) for x in izip(*[islice(products, i, None, 2) for i in range(2)])] 

print sums # should be [5.0, 7.0, 9.0] 
+0

Non è questo ciò che ha appena in modulo di lista? – squiguy

+0

no, perché * potrebbe * sostituire "sum" con .8 * x [0] + .2 * x [1] – Crisfole

+0

@ChristopherPfohl Beh, certo, ma ho pensato che fosse stato notato nei commenti. – squiguy

4
>>> a = (1, 2, 3) 
>>> b = (4, 5, 6) 
>>> def averageWeightedSum(args): 
     return sum(args)/len(args) 
>>> tuple(map(averageWeightedSum, zip(a, b))) 
(2.5, 3.5, 4.5) 

Un'alternativa sarebbe quella di applicare i pesi prima. Ciò consentirebbe anche di avere pesi differenti:

>>> from operator import mul 
>>> weights = (0.3, 0.7) 
>>> tuple(sum(map(mul, x, weights)) for x in zip(a, b)) 
(3.0999999999999996, 4.1, 5.1) 
>>> weights = (0.5, 0.5) 
>>> tuple(sum(map(mul, x, weights)) for x in zip(a, b)) 
(2.5, 3.5, 4.5) 
2

prendere la formula per la somma ponderata di una coppia di coordinate, e formano una tupla con un iteratore su ciascuna coppia (notare le due variabili dopo la for):

tuple(0.5*an + 0.5*bn for an, bn in zip(a, b)) 

Ciò lo rende semplice e leggibile come un unico rivestimento. Naturalmente se la tua "somma ponderata" è una funzione complicata, la definiresti prima come funzione separata.

+0

'tupla (somma (x) per x in zip (a, b))' ** è migliore ... e ** 'tupla (mappa (somma, zip (a, b)))' ** è pari meglio**. – Nawaz

+0

@Nawaz, perché è meglio? Dico che 'sum()' è peggio. Se si desidera una somma ponderata, 'sum()' è inutile. Inoltre, è una questione di gusti, ma trovo che 'sum()' è più appropriato quando c'è un numero indefinito di sommari - qui sono sempre aggiunti due termini. A ciascuno di loro, immagino, ma non dimenticare che la somma ponderata fa parte della domanda dell'OP. – alexis

+0

Ohh .. Non ho notato il peso. Ma poi la prima forma può ancora funzionare come: 'tupla (0.5 * sum (x) per x in zip (a, b))'. È quasi uguale al tuo, solo che è più funzionale (e probabilmente anche pythonic). – Nawaz

2

Se non ti dispiace la dipendenza, è possibile utilizzare NumPy per le operazioni sugli array elementwise

>>> import numpy as np 
>>> a = np.array([1, 2, 3]) 
>>> b = np.array([3, 4, 5]) 
>>> a + b 
array([4, 6, 8]) 
0

Se le tuple contengono str oggetti:

list(map(''.join, zip('abc', '123'))) 
# Returns ['a1', 'b2', 'c3']