2013-05-14 13 views
5

Zastanawiam się, czy był szczególnie pythonic sposób dodawania dwóch krotek elementwise?Dodawanie dwóch krotek elementwise

tej pory (a i b są krotki), mam

map(sum, zip(a, b)) 

Moje oczekiwany wynik będzie:

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

i ewentualnego ważenia byłoby dać 0,5 wagę i b 0.5 waga lub tak dalej. (Próbuję wziąć średnią ważoną).

Co działa dobrze, ale powiedz, że chciałem dodać wagę, nie jestem do końca pewien, jak bym to zrobił.

Dzięki

+0

Jaki jest twój oczekiwany wynik wtedy? – msvalkon

+1

Ty * przetwarzasz * swoje elementy kłamstw 'a' i' b'. Możesz także zrobić 'tuple (suma (aa, bb) dla aa, bb w zip (a, b))' aby rozpakować dwa elementy do oddzielnych zmiennych. Jaka byłaby Twoja formuła ważenia? –

+0

I zamiast tylko 'sum (i)' (lub 'sum (aa, bb)' w tym przypadku), możesz użyć * innego * wyrażenia, aby utworzyć inne elementy. W tym krotka z sumą i innymi wartościami: '(suma (aa, bb), aa/bb) na przykład. –

Odpowiedz

13

Zapnij je, a następnie zsumuj każdą krotkę.

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

EDIT: Oto lepiej, aczkolwiek bardziej skomplikowanej wersji, która pozwala na ważenie.

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

Czy to nie jest to, co właśnie ma formularz listy? – squiguy

+0

nie, ponieważ on * może * zamienić "sumę" na .8 * x [0] + .2 * x [1] – Crisfole

+0

@ChristopherPfohl Na pewno, ale myślałem, że to zostało odnotowane w komentarzach. – 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) 

Alternatywą byłoby zastosowanie wagi pierwszy. To także pozwala mieć różne ciężary:

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

przybrać formułę ważonej sumy jednej pary współrzędnych i forma krotki z iteratora nad każdą parą (uwaga na dwie zmienne zachodzących po for):

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

To sprawia, że ​​jest on prosty i czytelny jako jednolinijkowy. Oczywiście, jeśli twoja "ważona suma" jest skomplikowaną funkcją, musisz najpierw zdefiniować ją jako osobną funkcję.

+0

'krotka (suma (x) dla x w zamek (a, b))' ** to lepiej ... a ** 'krotka (mapa (suma, ZIP (a, b)))' ** jest jeszcze lepszy**. – Nawaz

+0

@Nawaz, dlaczego jest lepiej? Mówię, że i'sum() 'jest gorszy. Jeśli chcesz mieć sumę ważoną, 'sum()' jest bezużyteczne. Poza tym jest to kwestia gustu, ale uważam, że 'sum()' jest bardziej odpowiednie, gdy istnieje nieskończona liczba zmiennych - tutaj zawsze dodawane są dwie frazy. Do każdego z nich, jak sądzę, ale nie zapominajcie, że ważona kwota jest częścią pytania OP. – alexis

+0

Ohh .. Nie zauważyłem wagi. Ale wtedy pierwsza forma może nadal działać jako: 'tuple (0,5 * suma (x) dla x w zip (a, b))'. Jest prawie taki sam jak twój, tylko że jest bardziej funkcjonalny (i prawdopodobnie również pytony). – Nawaz

2

Jeśli nie przeszkadza zależność można użyć numpy dla operacji elementwise na tablicach

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

Jeśli krotki zawierać str obiekty:

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