Elementowe dodanie 2 list?

244

Mam teraz:

list1 = [1, 2, 3]
list2 = [4, 5, 6]

Chciałbym mieć:

[1, 2, 3]
 +  +  +
[4, 5, 6]
|| || ||
[5, 7, 9]

Po prostu elementarne dodanie dwóch list.

Z pewnością mogę powtórzyć te dwie listy, ale nie chcę tego robić.

Jaki jest najbardziej Pythoniczny sposób ?

Hazard Sibbs
źródło
Możliwy duplikat zwięzłego dodawania wektora w Pythonie?
Nikos Alexandris,

Odpowiedzi:

364

Używaj mapz operator.add:

>>> from operator import add
>>> list( map(add, list1, list2) )
[5, 7, 9]

lub zipze zrozumieniem listy:

>>> [sum(x) for x in zip(list1, list2)]
[5, 7, 9]

Porównanie czasowe:

>>> list2 = [4, 5, 6]*10**5
>>> list1 = [1, 2, 3]*10**5
>>> %timeit from operator import add;map(add, list1, list2)
10 loops, best of 3: 44.6 ms per loop
>>> %timeit from itertools import izip; [a + b for a, b in izip(list1, list2)]
10 loops, best of 3: 71 ms per loop
>>> %timeit [a + b for a, b in zip(list1, list2)]
10 loops, best of 3: 112 ms per loop
>>> %timeit from itertools import izip;[sum(x) for x in izip(list1, list2)]
1 loops, best of 3: 139 ms per loop
>>> %timeit [sum(x) for x in zip(list1, list2)]
1 loops, best of 3: 177 ms per loop
Ashwini Chaudhary
źródło
10
Jeśli używasz tych ogromnych tablic, rozwiązanie numpy autorstwa @BasSwinckels jest prawdopodobnie czymś, na co powinieneś zwrócić uwagę.
Henry Gomersall,
1
Jakiej wersji Python używałeś do tych czasów?
arshajii
9
NB - w python3 funkcja map () zwraca raczej iterowalną rzecz niż listę. Jeśli potrzebujesz prawdziwej listy, pierwszą odpowiedzią jest lista (mapa (dodaj, lista 1, lista 2))
FLHerne
Zwrócenie uwagi na problem Python3 zauważony przez @FLHerne z czasem mapbędzie coraz ważniejszy. Python 2 straci oficjalne wsparcie za mniej niż 3 lata.
nealmcb
1
Wiele razy składnia Pythona jest naprawdę elegancka i prosta, ale niestety nie jest to jedna z nich. A przy tak prostym zadaniu szkoda… Dlaczego mieliby łączyć „+” z listami, skoro istnieje już metoda .extend ()?
Nic Scozzaro,
105

Inni podali przykłady, jak to zrobić w czystym pythonie. Jeśli chcesz to zrobić z tablicami zawierającymi 100 000 elementów, powinieneś użyć numpy:

In [1]: import numpy as np
In [2]: vector1 = np.array([1, 2, 3])
In [3]: vector2 = np.array([4, 5, 6])

Wykonanie dodawania elementów jest teraz tak proste jak

In [4]: sum_vector = vector1 + vector2
In [5]: print sum_vector
[5 7 9]

tak jak w Matlabie.

Czas porównania z najszybszą wersją Ashwini:

In [16]: from operator import add
In [17]: n = 10**5
In [18]: vector2 = np.tile([4,5,6], n)
In [19]: vector1 = np.tile([1,2,3], n)
In [20]: list1 = [1,2,3]*n
In [21]: list2 = [4,5,6]*n
In [22]: timeit map(add, list1, list2)
10 loops, best of 3: 26.9 ms per loop

In [23]: timeit vector1 + vector2
1000 loops, best of 3: 1.06 ms per loop

To jest współczynnik 25 szybciej! Ale użyj tego, co pasuje do twojej sytuacji. W przypadku prostego programu prawdopodobnie nie chcesz instalować numpy, więc użyj standardowego Pythona (i uważam, że wersja Henry'ego jest najbardziej Pythoniczna). Jeśli jesteś w poważnej sytuacji kryzysowej, pozwól, aby numpyciężkie podnoszenie. Dla maniaków prędkości: wydaje się, że numpy rozwiązanie jest szybsze od początku n = 8.

Bas Swinckels
źródło
59
[a + b for a, b in zip(list1, list2)]
Henry Gomersall
źródło
4
@deltab Zaakceptowana odpowiedź jest szybsza I zawiera tę odpowiedź (więcej informacji)
Sibbs Gambling
2
@ perfectionm1ng, chociaż rozumiem twój punkt (i nie żałuję tego ani trochę) Pomyślałem, że warto wskazać, że zawsze skorzystam z przedstawionego przeze mnie rozwiązania (które, biorąc pod uwagę, że nie wymaga importu, jest prawdopodobnie najprostsze) jako prawdopodobnie bardziej pythonowy) lub tam, gdzie liczy się prędkość, odpowiedź Bas Swinckel , która jest w przeważającej mierze właściwą opcją , gdy liczy się prędkość.
Henry Gomersall,
Tak. Dziękuję za opinię. Ale w zasadzie [sum(x) for x in zip(list1, list2)]to ta sama odpowiedź, co nie? :)
Sibbs Gambling
4
@ perfectionm1ng Mniej więcej (chociaż został dodany po moim z edycją :). Osobiście wolę notację a + b z jawnym rozpakowaniem krotki dla czytelności i pytoniczności.
Henry Gomersall,
12

Jak opisują inni, szybkie i zajmujące mało miejsca rozwiązanie wykorzystuje numpy (np) z wbudowanymi możliwościami manipulowania wektorem:

1. Z Numpy

x = np.array([1,2,3])
y = np.array([2,3,4])
print x+y

2. Z wbudowanymi

2.1 Lambda

list1=[1, 2, 3]
list2=[4, 5, 6]
print map(lambda x,y:x+y, list1, list2)

Zauważ, że map () obsługuje wiele argumentów.

2.2 zip i zrozumienie listy

list1=[1, 2, 3]
list2=[4, 5, 6]
print [x + y for x, y in zip(list1, list2)]
Program MasterControl
źródło
1
+1 za podejście lambda. Szkoda, że ​​to rozwiązanie jest łączone z innymi rozwiązaniami, które są powielane gdzie indziej.
LondonRob
10

Z numpymojej opinii jest łatwiejszy w użyciu :

import numpy as np
list1=[1,2,3]
list2=[4,5,6]
np.add(list1,list2)

Wyniki:

Wykonanie terminala

Aby uzyskać szczegółowe informacje o parametrach, sprawdź tutaj: numpy.add

Ludwig Zhou
źródło
6

Być może „najbardziej pythonowy sposób” powinien obejmować obsługę przypadku, w którym lista1 i lista2 nie są tego samego rozmiaru. Zastosowanie niektórych z tych metod da ci cichą odpowiedź. Podejście numpy da ci znać, najprawdopodobniej z ValueError.

Przykład:

import numpy as np
>>> list1 = [ 1, 2 ]
>>> list2 = [ 1, 2, 3]
>>> list3 = [ 1 ]
>>> [a + b for a, b in zip(list1, list2)]
[2, 4]
>>> [a + b for a, b in zip(list1, list3)]
[2]
>>> a = np.array (list1)
>>> b = np.array (list2)
>>> a+b
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: operands could not be broadcast together with shapes (2) (3)

Którego wyniku możesz chcieć, jeśli miałbyś jakąś funkcję w twoim problemie?

Fred Mitchell
źródło
w tym przypadku należy zdecydowanie patrzeć zip_longestz itertools z fillvalueo 0.
Ma0
6

To jest proste z numpy.add()

import numpy

list1 = numpy.array([1, 2, 3])
list2 = numpy.array([4, 5, 6])
result = numpy.add(list1, list2) # result receive element-wise addition of list1 and list2
print(result)
array([5, 7, 9])

Zobacz dokument tutaj

Jeśli chcesz otrzymać listę python:

result.tolist()
Eduardo Basílio
źródło
5

Będzie to działać na 2 lub więcej listach; iterowanie po liście list, ale przy użyciu dodawania numpy do radzenia sobie z elementami każdej listy

import numpy as np
list1=[1, 2, 3]
list2=[4, 5, 6]

lists = [list1, list2]
list_sum = np.zeros(len(list1))
for i in lists:
   list_sum += i
list_sum = list_sum.tolist()    

[5.0, 7.0, 9.0]
litepresence
źródło
5

Być może jest to pytoniczne i nieco przydatne, jeśli masz nieznaną liczbę list i bez importowania czegokolwiek.

Dopóki listy są tej samej długości, możesz korzystać z poniższej funkcji.

W tym przypadku * args akceptuje zmienną liczbę argumentów listy (ale sumuje tylko taką samą liczbę elementów w każdym).

* Jest ponownie używane na zwróconej liście do rozpakowywania elementów na każdej z list.

def sum_lists(*args):
    return list(map(sum, zip(*args)))

a = [1,2,3]
b = [1,2,3]  

sum_lists(a,b)

Wynik:

[2, 4, 6]

Lub z 3 listami

sum_lists([5,5,5,5,5], [10,10,10,10,10], [4,4,4,4,4])

Wynik:

[19, 19, 19, 19, 19]
Skrzydło
źródło
3

Użyj mapy z funkcją lambda:

>>> map(lambda x, y: x + y, list1, list2)
[5, 7, 9]
Peaters
źródło
3

Nie ustaliłem czasu, ale podejrzewam, że byłoby to dość szybkie:

import numpy as np
list1=[1, 2, 3]
list2=[4, 5, 6]

list_sum = (np.add(list1, list2)).tolist()

[5, 7, 9]
litepresence
źródło
3

Jeśli potrzebujesz obsługiwać listy o różnych rozmiarach, nie martw się! Wspaniały moduł itertools obejmuje:

>>> from itertools import zip_longest
>>> list1 = [1,2,1]
>>> list2 = [2,1,2,3]
>>> [sum(x) for x in zip_longest(list1, list2, fillvalue=0)]
[3, 3, 3, 3]
>>>

W Python 2 zip_longestnazywa się izip_longest.

Zobacz także tę odpowiednią odpowiedź i komentarz do innego pytania .

jjst
źródło
3
[list1[i] + list2[i] for i in range(len(list1))]
wgr
źródło
1
Więcej python byłby[a + b for (a, b) in zip(list1, list2)]
rayryeng
2

Chociaż rzeczywiste pytanie nie chce powtarzać się po liście, aby wygenerować wynik, ale wszystkie zaproponowane rozwiązania działają dokładnie tak, jak pod maską!

Aby odświeżyć: Nie można dodać dwóch wektorów bez spojrzenia na wszystkie elementy wektorowe. Zatem złożoność algorytmiczna większości z tych rozwiązań to Big-O (n). Gdzie n jest wymiarem wektora.

Zatem z algorytmicznego punktu widzenia użycie iteracyjnej pętli for do wygenerowania wynikowej listy jest logiczne i pythoniczne. Jednak dodatkowo ta metoda nie wiąże się z koniecznością nazywania lub importowania dodatkowej biblioteki.

# Assumption: The lists are of equal length.
resultList = [list1[i] + list2[i] for i in range(len(list1))]

Pokazane tu / omówione czasy są zależne od systemu i implementacji i nie mogą być wiarygodnym pomiarem do pomiaru wydajności operacji. W każdym razie duża złożoność O operacji dodawania wektora jest liniowa, co oznacza O (n).

Ehsan
źródło
1
a_list = []
b_list = []
for i in range(1,100):
    a_list.append(random.randint(1,100))

for i in range(1,100):
    a_list.append(random.randint(101,200))
[sum(x) for x in zip(a_list , b_list )]
DSBLR
źródło