2008-11-04 23 views
33

Estoy bastante seguro de que debería haber una forma más pitonica de hacerlo, pero no puedo pensar en una: ¿cómo puedo fusionar una lista bidimensional en una lista unidimensional? Algo así como zip/map pero con más de dos iteradores.Fusionando/agregando listas en Python

Ejemplo - He la siguiente lista: Hasta ahora lo que he llegado con

array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] 

Quiero tener

result = [12, 15, 18] # [1+4+7, 2+5+8, 3+6+9] 

es:

def add_list(array): 
    number_items = len(array[0]) 
    result = [0] * number_items 
    for index in range(number_items): 
     for line in array: 
      result[index] += line[index] 
    return result 

Pero eso no se ve muy elegante/Pythonic para mí. Además de no verificar si todas las "líneas" en la matriz 2D son de la misma longitud, pueden agregarse entre sí, etc. ¿Cuál sería una mejor manera de hacerlo?

Respuesta

69
[sum(a) for a in zip(*array)] 
63

[la suma (valor) para el valor en zip (* array)] es bastante estándar.

Esto podría ayudar a entender que:

In [1]: array=[[1, 2, 3], [4, 5, 6], [7, 8, 9]] 

In [2]: array 
Out[2]: [[1, 2, 3], [4, 5, 6], [7, 8, 9]] 

In [3]: *array 
------------------------------------------------------------ 
    File "<ipython console>", line 1 
    *array 
    ^
<type 'exceptions.SyntaxError'>: invalid syntax 

La estrella unario no es un operador por sí mismo. Desenreda los elementos de la matriz en argumentos en llamadas a funciones.

In [4]: zip(*array) 
Out[4]: [(1, 4, 7), (2, 5, 8), (3, 6, 9)] 

postal() es una función integrada de

In [5]: zip(*array)[0] 
Out[5]: (1, 4, 7) 

cada elemento de la lista devuelta por zip es un conjunto de números que desea.

In [6]: sum(zip(*array)[0]) 
Out[6]: 12 

In [7]: [sum(values) for values in zip(*array)] 
Out[7]: [12, 15, 18] 
8

Si estás haciendo una gran cantidad de este tipo de cosas, que quieren aprender acerca de scipy.

>>> import scipy 
>>> sum(scipy.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])) 
array([12, 15, 18]) 

Todos los tamaños de matriz se comprueban de forma automática. La suma se realiza en C puro, por lo que es muy rápido. Las matrices scipy también son muy eficientes en la memoria.

El inconveniente es que depende de un módulo de terceros bastante complejo. Pero esa es una muy buena compensación para muchos propósitos.

14

Una forma alternativa:

map(sum, zip(*array)) 
3

De acuerdo con fivebells, pero también se puede utilizar Numpy, que es un pequeño (importaciones más rápido) y una aplicación más genérica de cosas tipo array. (en realidad, es una dependencia de scipy). Estas son excelentes herramientas que, como se ha dicho, son 'imprescindibles' si se trata de este tipo de manipulaciones.

2

tarde al juego, y no es tan bueno de una respuesta como algunos de los otros, pero pensé que era una especie de mono:

map(lambda *x:sum(x),*array) 

es una lástima que sum(1,2,3) no funciona.Si lo hiciera, podríamos eliminar el tonto lambda allí, pero supongo que eso dificultaría discernir cuál (si alguno) de los elementos es el "inicio" de la suma. Tendría que cambiar eso a una palabra clave única discusión que rompería muchas secuencias de comandos ... Oh bien. Supongo que viviremos con lambda.

0

[suma de (a) para una en zip (* array)]

me gusta. Necesitaba algo relacionado para intercalar los objetos a una lista de elementos, se le ocurrió algo similar pero más concisa, incluso para las listas de longitud:

sum(zip(*array),()) 

por ejemplo, entrelazando dos listas:

a = [1,2,3] 
b = ['a','b','c'] 
sum(zip(a,b),()) 
(1, 'a', 2, 'b', 3, 'c') 
+0

Hm, aunque interesante, no es realmente una respuesta a esta pregunta (y, por lo tanto, puede atraer votos a la baja). Podría, por ejemplo, hacer la pregunta "¿Cómo puedo intercalar varias listas?" y responde tú mismo. Tal vez use un ejemplo que use más de dos listas; de lo contrario, alguien sugerirá '", ". Join (a)'. –

+0

Tim acordó. Es un apropros de este 'q & a' apuntado por un hilo que trata listas de entrelazado, ¡pero marcado como un duplicado de esta pregunta! Usé ',' en el ejemplo, solo por simplicidad, mi código requería listas reales de clases definidas por el usuario para ser intercaladas, pero eso sería difícil de excusar en abstracto. – F1Rumors

0

Puede simplemente hacer esto:

print [sum(x) for x in zip(*array)] 

Si desea iterar a través de las listas de esta manera, puede utilizar chain del módulo itertools:

from itertools import chain 

for x in array.chain.from_iterable(zip(*array)): 
    print x 
# prints 1, 4, 7, 2, 5, 8, ...