web-dev-qa-db-fra.com

Addition élément par élément de 2 listes?

J'ai maintenant:

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

Je souhaite avoir:

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

Simplement un ajout élémentaire de deux listes.

Je peux sûrement parcourir les deux listes, mais je ne veux pas le faire.

Quelle est la manière la plus pythonique de le faire?

214
Sibbs Gambling

Utilisez map avec operator.add :

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

ou Zip avec une liste de compréhension:

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

Comparaisons de temps:

_>>> 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
_
320
Ashwini Chaudhary

Les autres ont donné des exemples sur la manière de faire cela en python pur. Si vous voulez faire cela avec des tableaux avec 100.000 éléments, vous devriez utiliser numpy:

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

Faire l’addition élément par élément est maintenant aussi trivial que

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

comme dans Matlab.

Calendrier à comparer avec la version la plus rapide d'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

C'est donc un facteur 25 plus rapide! Mais utilisez ce qui convient à votre situation. Pour un programme simple, vous ne voulez probablement pas installer numpy, utilisez donc la norme python (et je trouve que la version de Henry est la plus pythonique). Si vous êtes sérieux dans le calcul, laissez numpy faire le gros du travail. Pour les amateurs de vitesse: il semble que la solution numpy soit plus rapide à partir de n = 8.

93
Bas Swinckels
[a + b for a, b in Zip(list1, list2)]
54
Henry Gomersall

Comme décrit par d’autres, une solution rapide et peu encombrante utilise numpy (np) avec sa capacité intégrée de manipulation de vecteurs:

1. Avec Numpy

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

2. Avec éléments intégrés

2.1 Lambda

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

Notez que map () supporte plusieurs arguments.

2.2 Zip et compréhension de la liste

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

Il est plus simple d'utiliser numpy de mon point de vue:

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

Résultats:

Terminal execution

Pour des informations détaillées sur les paramètres, vérifiez ici: numpy.add

6
Ludwig Zhou

C'est simple avec 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])

Voir doc ici

Si vous souhaitez recevoir une liste python:

result.tolist()
5
Eduardo Basílio

Peut-être que "la manière la plus pythonique" devrait inclure la gestion du cas où list1 et list2 ne sont pas de la même taille. L'application de certaines de ces méthodes vous donnera tranquillement une réponse. L’approche numpy vous le fera savoir, très probablement avec ValueError.

Exemple:

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)

Quel résultat voudriez-vous si cela faisait partie de votre problème?

4
Fred Mitchell

Cela fonctionnera pour 2 listes ou plus; parcourir la liste des listes, mais utiliser numpy addition pour traiter les éléments de chaque liste

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

Peut-être que c'est Pythonic et légèrement utile si vous avez un nombre inconnu de listes et sans rien importer.

Tant que les listes ont la même longueur, vous pouvez utiliser la fonction ci-dessous.

Ici, l'argument * accepte un nombre variable d'arguments de liste (mais ajoute seulement le même nombre d'éléments dans chacun).

Le * est à nouveau utilisé dans la liste renvoyée pour décompresser les éléments de chacune des listes.

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

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

sum_lists(a,b)

Sortie:

[2, 4, 6]

Ou avec 3 listes

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

Sortie:

[19, 19, 19, 19, 19]
3
Wing

Je ne l'ai pas chronométré mais je suppose que cela serait assez rapide:

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

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

[5, 7, 9]
2
litepresence

Utilisez la carte avec la fonction lambda:

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

Si vous avez besoin de gérer des listes de tailles différentes, ne vous inquiétez pas! Le merveilleux module itertools vous a couvert:

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

Dans Python 2, _Zip_longest_ est appelé izip_longest .

Voir aussi cette réponse pertinente et commenter une autre question .

1
jjst

Bien que la question ne veuille pas parcourir la liste pour générer le résultat, toutes les solutions proposées font exactement cela sous le capot!

Pour actualiser: Vous ne pouvez pas ajouter deux vecteurs sans examiner tous les éléments vectoriels. La complexité algorithmique de la plupart de ces solutions est donc Big-O (n). Où n est la dimension du vecteur.

Donc, d’un point de vue algorithmique, utiliser une boucle for pour générer de manière itérative la liste résultante est logique et Pythonic aussi. Toutefois, en outre, cette méthode ne nécessite pas l’appel ou l’importation d’une bibliothèque supplémentaire.

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

Les délais présentés/discutés ici dépendent du système et de la mise en œuvre et ne peuvent constituer une mesure fiable pour mesurer l'efficacité de l'opération. Dans tous les cas, la grande complexité en O de l'opération d'addition de vecteur est linéaire, ce qui signifie O (n).

1
Ehsan
[list1[i] + list2[i] for i in range(len(list1))]
1
wgr
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 )]
0
DSBLR