Elementowe dodanie 2 list?


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

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.


59
[a + b for a, b in zip(list1, list2)]

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

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


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?


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

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]

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]

3

Użyj mapy z funkcją lambda:

>>> map(lambda x, y: x + y, list1, list2)
[5, 7, 9]

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]


3
[list1[i] + list2[i] for i in range(len(list1))]

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


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 )]
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.