vectorized vectorize multiply index array python list elementwise-operations
itertools

python - vectorize - ¿Elemento inteligente de 2 listas?



to array python (13)

Ahora tengo:

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

Deseo tener:

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

Simplemente una adición inteligente de elementos de dos listas.

Seguramente puedo repetir las dos listas, pero no quiero hacer eso.

¿Cuál es la forma más pitonica de hacerlo?


Aunque, la pregunta real no quiere iterar sobre la lista para generar el resultado, ¡pero todas las soluciones que se han propuesto hacen exactamente eso debajo del capó!

Para actualizar: no puede agregar dos vectores sin examinar todos los elementos del vector. Entonces, la complejidad algorítmica de la mayoría de estas soluciones es Big-O (n). Donde n es la dimensión del vector.

Entonces, desde un punto de vista algorítmico, usar un ciclo for para generar iterativamente la lista resultante es lógico y también pitónico. Sin embargo, además, este método no tiene la sobrecarga de llamar o importar cualquier biblioteca adicional.

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

Los tiempos que se muestran / discuten aquí dependen del sistema y la implementación, y no pueden ser una medida confiable para medir la eficiencia de la operación. En cualquier caso, la gran complejidad O de la operación de adición de vectores es lineal, lo que significa O (n).


Es más simple usar numpy desde mi opinión:

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

Resultados:

Para obtener información detallada de los parámetros, consulte aquí: numpy.add


Esto es simple 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])

Ver doc aquí

Si quieres recibir una lista de Python:

result.tolist()


Esto funcionará para 2 o más listas; iterando a través de la lista de listas, pero usando numpy además para tratar con los elementos de cada lista

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]


Los otros dieron ejemplos de cómo hacer esto en python puro. Si desea hacer esto con matrices con 100.000 elementos, debe usar numpy:

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

Hacer la adición inteligente de elementos ahora es tan trivial como

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

como en Matlab.

Tiempo para comparar con la versión más rápida de 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

¡Así que este es un factor 25 más rápido! Pero usa lo que se adapte a tu situación. Para un programa simple, probablemente no desee instalar numpy, entonces use python estándar (y creo que la versión de Henry es la más pitónica). Si te numpy crujidos numéricos serios, deja que numpy haga el trabajo pesado. Para los fanáticos de la velocidad: parece que la solución numpy es más rápida comenzando alrededor de n = 8 .


No lo he cronometrado pero sospecho que esto sería bastante rápido:

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


Quizás "la forma más pitonica" debe incluir el manejo del caso donde lista1 y lista2 no son del mismo tamaño. La aplicación de algunos de estos métodos silenciosamente le dará una respuesta. El enfoque numpy le permitirá saber, muy probablemente con un ValueError.

Ejemplo:

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)

¿Qué resultado podría desear si esto estuviera en una función en su problema?


Según lo descrito por otros, una solución rápida y también eficiente en el uso de espacio es usar numpy (np) con su capacidad de manipulación de vectores incorporada:

1. Con Numpy

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

2. Con complementos

2.1 Lambda

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

Tenga en cuenta que map () admite múltiples argumentos.

2.2 zip y lista de comprensión

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


Si necesita manejar listas de diferentes tamaños, ¡no se preocupe! El maravilloso módulo itertools tiene cubierto:

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

En Python 2, zip_longest se llama izip_longest .

Vea también esta respuesta relevante y comente sobre otra pregunta .


Utilice el map con operator.add :

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

o zip con una lista de comprensión:

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

Comparaciones de tiempo:

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


Utilice el mapa con la función lambda:

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


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


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