Aggiunta saggia di 2 liste?


Risposte:


364

Utilizzare mapcon operator.add:

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

o zipcon una comprensione dell'elenco:

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

Confronti temporali:

>>> 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
Se usi questi enormi array, la soluzione insensibile di @BasSwinckels è probabilmente qualcosa che dovresti guardare.
Henry Gomersall,

1
Quale versione di Python hai usato per quei tempi?
arshajii,

9
NB: in python3, map () restituisce un oggetto iterabile piuttosto che un elenco. Se hai bisogno di un elenco reale, la prima risposta è elenco (mappa (aggiungi, elenco1, elenco2))
FLHerne

Notando il problema di python3 notato da @FLHerne con mapdiventerà sempre più importante nel tempo. Python 2 perderà il supporto ufficiale in meno di 3 anni.
nealmcb,

1
Ci sono molte volte in cui la sintassi di Python è davvero elegante e semplice, ma sfortunatamente questa non è una di queste. E per un compito così semplice, è un peccato .... Perché dovrebbero rendere "+" concatenate le liste quando c'è già il metodo .extend ()?
Nic Scozzaro,

105

Gli altri hanno fornito esempi su come farlo in puro pitone. Se vuoi farlo con array con 100.000 elementi, dovresti usare numpy:

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

Fare l'aggiunta in termini di elementi ora è banale come

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

proprio come in Matlab.

Tempi per confrontare con la versione più veloce di 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

Quindi questo è un fattore 25 più veloce! Ma usa ciò che si adatta alla tua situazione. Per un semplice programma, probabilmente non vuoi installare numpy, quindi usa Python standard (e trovo la versione di Henry la più Pythonic). Se ti piacciono i gravi scricchiolii, numpyfai il sollevamento di carichi pesanti. Per i maniaci della velocità: sembra che la soluzione insensibile sia più veloce iniziando n = 8.


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

4
@deltab La risposta accettata è più rapida E contiene questa risposta (più informativa)
Sibbs Gambling

2
@ perfectionm1ng anche se capisco il tuo punto (e non lo rammarico un po ') Ho solo pensato che valesse la pena sottolineare che avrei sempre usato la soluzione che ho presentato (che dato che non richiede importazioni è probabilmente anche la più semplice come probabilmente il più pitonico), o dove conta la velocità, la risposta di Bas Swinckel , che è assolutamente l'opzione giusta dove la velocità conta.
Henry Gomersall,

Sì. Grazie per l'opinione. Ma essenzialmente [sum(x) for x in zip(list1, list2)]è la stessa della tua risposta, no? :)
Sibbs Gambling

4
@ perfectionm1ng Più o meno (anche se è stato aggiunto dopo il mio con una modifica :). Personalmente, preferisco la notazione a + b con decompressione esplicita della tupla per leggibilità e pitonia.
Henry Gomersall,

12

Come descritto da altri, una soluzione veloce e allo stesso tempo efficiente in termini di spazio sta usando numpy (np) con la sua capacità di manipolazione vettoriale integrata:

1. Con Numpy

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

2. Con built-in

2.1 Lambda

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

Si noti che map () supporta più argomenti.

2.2 Comprensione zip ed elenco

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

1
+1 per l'approccio lambda. È un peccato che questa soluzione sia combinata con altre soluzioni che sono duplicate altrove.
London,

10

È più semplice da usare numpydalla mia opinione:

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

risultati:

Esecuzione del terminale

Per informazioni dettagliate sui parametri, consultare qui: numpy.add


6

Forse "il modo più pitonico" dovrebbe includere la gestione del caso in cui list1 e list2 non hanno le stesse dimensioni. L'applicazione di alcuni di questi metodi ti darà tranquillamente una risposta. L'approccio intorpidito ti farà sapere, molto probabilmente con un ValueError.

Esempio:

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)

Quale risultato potresti desiderare se questo avesse una funzione nel tuo problema?


in questo caso si dovrebbe assolutamente guardare zip_longestdagli itertools con un fillvaluedi 0.
Ma0

6

Questo è semplice con 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])

Vedi doc qui

Se si desidera ricevere un elenco Python:

result.tolist()

5

Questo funzionerà per 2 o più liste; scorrendo l'elenco degli elenchi, ma utilizzando l'aggiunta numpy per gestire gli elementi di ciascun elenco

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

Forse questo è pitonico e leggermente utile se si dispone di un numero sconosciuto di elenchi e senza importare nulla.

Finché gli elenchi hanno la stessa lunghezza, è possibile utilizzare la funzione seguente.

Qui * args accetta un numero variabile di argomenti dell'elenco (ma somma solo lo stesso numero di elementi in ciascuno).

* Viene nuovamente utilizzato nell'elenco restituito per decomprimere gli elementi in ciascuno degli elenchi.

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

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

sum_lists(a,b)

Produzione:

[2, 4, 6]

O con 3 liste

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

Produzione:

[19, 19, 19, 19, 19]

3

Usa la mappa con la funzione lambda:

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

3

Non l'ho cronometrato ma sospetto che questo sarebbe piuttosto veloce:

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
Più pitonico sarebbe[a + b for (a, b) in zip(list1, list2)]
rayryeng

2

Tuttavia, la vera domanda non vuole scorrere l'elenco per generare il risultato, ma tutte le soluzioni che sono state proposte fanno esattamente quello che sta sotto!

Per aggiornare: non è possibile aggiungere due vettori senza esaminare tutti gli elementi vettoriali. Quindi, la complessità algoritmica della maggior parte di queste soluzioni è Big-O (n). Dove n è la dimensione del vettore.

Quindi, da un punto di vista algoritmico, usare un ciclo for per generare iterativamente l'elenco risultante è anche logico e pitonico. Tuttavia, inoltre, questo metodo non ha l'overhead di chiamare o importare alcuna libreria aggiuntiva.

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

I tempi che vengono mostrati / discussi qui dipendono dal sistema e dall'implementazione e non possono essere misure affidabili per misurare l'efficienza dell'operazione. In ogni caso, la grande complessità O dell'operazione di addizione vettoriale è lineare, ovvero 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 )]
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.