Elementsgewijze toevoeging van 2 lijsten?

Ik heb nu:

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

Ik wil hebben:

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

Gewoon een elementgewijze toevoeging van twee lijsten.

Ik kan de twee lijsten zeker herhalen, maar dat wil ik niet.

Wat is de meest Pythonische manierom dit te doen?


Antwoord 1, autoriteit 100%

Gebruik mapmet operator.add:

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

of zipmet een lijst begrip:

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

Timing vergelijkingen:

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

Antwoord 2, autoriteit 28%

De anderen gaven voorbeelden hoe je dit in pure python kunt doen. Als je dit wilt doen met arrays met 100.000 elementen, moet je numpy gebruiken:

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

Het elementsgewijs toevoegen is nu net zo triviaal als

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

net als in Matlab.

Timing om te vergelijken met Ashwini’s snelste versie:

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

Dit is dus een factor 25 sneller! Maar gebruik wat bij jouw situatie past. Voor een eenvoudig programma wil je waarschijnlijk niet numpy installeren, dus gebruik standaard python (en ik vind Henry’s versiede meest Pythonic een). Als je serieus met cijfers bezig bent, laat numpydan het zware werk doen. Voor de snelheidsfreaks: het lijkt erop dat de numpy-oplossing sneller is vanaf n = 8.


Antwoord 3, autoriteit 16%

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

Antwoord 4, autoriteit 3%

Zoals beschreven door anderen, is een snelle en ook ruimtebesparende oplossing het gebruik van numpy (np) met zijn ingebouwde vectormanipulatiemogelijkheid:

1. Met Numpy

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

2. Met ingebouwde

2.1 Lambda

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

Merk op dat map() meerdere argumenten ondersteunt.

2.2 begrip van zip en lijst

list1=[1, 2, 3]
list2=[4, 5, 6]
print [x + y for x, y in zip(list1, list2)]

Antwoord 5, autoriteit 3%

Het is naar mijn mening eenvoudiger om numpyte gebruiken:

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

Resultaten:

Terminal uitvoering

Kijk hier voor gedetailleerde parameterinformatie: numpy.add


Antwoord 6, autoriteit 2%

Misschien is dit pythonisch en enigszins handig als je een onbekend aantal lijsten hebt, en zonder iets te importeren.

Zolang de lijsten even lang zijn, kunt u de onderstaande functie gebruiken.

Hier accepteert de *args een variabel aantal lijstargumenten (maar telt alleen hetzelfde aantal elementen in elk op).

De * wordt opnieuw gebruikt in de geretourneerde lijst om de elementen in elk van de lijsten uit te pakken.

def sum_lists(*args):
    return list(map(sum, zip(*args)))
a = [1,2,3]
b = [1,2,3]  
sum_lists(a,b)

Uitvoer:

[2, 4, 6]

Of met 3 lijsten

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

Uitvoer:

[19, 19, 19, 19, 19]

Antwoord 7, autoriteit 2%

Misschien moet “de meest pythonische manier” het geval omvatten waarin lijst1 en lijst2 niet dezelfde grootte hebben. Als u enkele van deze methoden toepast, krijgt u stilletjes een antwoord. De numpy-aanpak zal u dit laten weten, hoogstwaarschijnlijk met een ValueError.

Voorbeeld:

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)

Welk resultaat zou je willen als dit een functie in je probleem was?


Antwoord 8

Dit is eenvoudig met 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])

Bekijk het document hier

Als je een pythonlijst wilt ontvangen:

result.tolist()

Antwoord 9

Dit werkt voor 2 of meer lijsten; itereren door de lijst met lijsten, maar numpy toevoeging gebruiken om elementen van elke lijst te behandelen

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]

Antwoord 10

Maak je geen zorgen als je lijsten van verschillende formaten moet verwerken! De prachtige itertools-module heeft u gedekt:

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

In Python 2 wordt zip_longestizip_longest.

Zie ook dit relevante antwoord en reageer op een andere vraag.


Antwoord 11

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

Antwoord 12

Gebruik kaart met lambda-functie:

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

Antwoord 13

Ik heb het niet getimed, maar ik vermoed dat dit vrij snel zou zijn:

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

Antwoord 14

Hoewel de eigenlijke vraag de lijst niet wil herhalen om het resultaat te genereren, maar alle voorgestelde oplossingen doen precies dat onder de motorkap!

Vernieuwen: u kunt geen twee vectoren toevoegen zonder naar alle vectorelementen te kijken. De algoritmische complexiteit van de meeste van deze oplossingen is dus Big-O(n). Waarbij n de dimensie van de vector is.

Dus, vanuit een algoritmisch oogpunt, is het gebruik van een for-lus om iteratief de resulterende lijst te genereren, ook logisch en pythonisch. Bovendien heeft deze methode niet de overhead van het aanroepen of importeren van een extra bibliotheek.

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

De timings die hier worden getoond/besproken zijn afhankelijk van het systeem en de implementatie en kunnen geen betrouwbare maatstaf zijn om de efficiëntie van de operatie te meten. Hoe dan ook, de grote O-complexiteit van de vectoroptelling is lineair, wat O(n) betekent.


Antwoord 15

  • De zip-functie is hier handig, gebruikt met een lijstbegrip v1, v2.
  • Als je een lijst met lijsten hebt (in plaats van slechts twee lijsten), kun je v3gebruiken.
  • Voor lijsten met verschillende lengtes (bijvoorbeeld: door 1 toe te voegen aan het einde van de eerste/tweede lijst), kunt u zoiets proberen (met zip_longest) – v4
first = [1, 2, 3, 1]
second = [4, 5, 6]
output: [5, 7, 9, 1]
  • Als je een onbekend aantal lijsten van dezelfde lengte hebt, kun je de functie v5gebruiken.

  • v6– De operatormodule exporteert een reeks efficiënte functies die overeenkomen met de intrinsieke operators van Python. operator.add(x, y)is bijvoorbeeld gelijk aan de uitdrukking x+y.

  • v7– Ervan uitgaande dat beide lijsten firsten seconddezelfde lengte hebben, heb je geen zip of iets anders nodig.

################
first = [1, 2, 3]
second = [4, 5, 6]
####### v1 ########
third1 = [sum(i) for i in zip(first,second)]
####### v2 ########
third2 = [x + y for x, y in zip(first, second)]
####### v3 ########
lists_of_lists = [[1, 2, 3], [4, 5, 6]]
third3 = [sum(x) for x in zip(*lists_of_lists)]
####### v4 ########
from itertools import zip_longest
third4 = list(map(sum, zip_longest(first, second, fillvalue=0)))
####### v5 ########
def sum_lists(*args):
    return list(map(sum, zip(*args)))
third5 = sum_lists(first, second)
####### v6 ########
import operator
third6 = list(map(operator.add, first,second))
####### v7 ########
third7 =[first[i]+second[i] for i in range(len(first))]
####### v(i) ########
print(third1) # [5, 7, 9]
print(third2) # [5, 7, 9]
print(third3) # [5, 7, 9]
print(third4) # [5, 7, 9]
print(third5) # [5, 7, 9]
print(third6) # [5, 7, 9]
print(third7) # [5, 7, 9]

Antwoord 16

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

Other episodes