Объединение / добавление списков в Python

Я уверен, что должен быть более Pythonic способ сделать это, но я не могу думать об одном: как я могу объединить двумерный список в одномерный список? Сорт вроде zip / map, но с более чем двумя итераторами.

Пример. У меня есть следующий список:

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

я хочу иметь

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

До сих пор я придумал:

 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 

Но это не выглядит очень элегантно / Pythonic для меня. Помимо того, что не проверяется, могут ли все «линии» в 2D-массиве иметь одинаковую длину, могут быть добавлены друг к другу и т. Д. Что было бы лучшим способом сделать это?

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

[сумма (значение) для значения в zip (* array)] довольно стандартная.

Это может помочь вам понять это:

 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 

Унарная звезда не является оператором сама по себе. Он разворачивает элементы массива в аргументы в вызовы функций.

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

zip () – встроенная функция

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

каждый элемент для списка, возвращаемого zip, представляет собой набор нужных чисел.

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

Альтернативный способ:

 map(sum, zip(*array)) 

Если вы делаете много такого, вы хотите узнать о scipy .

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

Все размеры массива проверяются автоматически. Сумма делается в чистом C, так что это очень быстро. scipy массивы также очень эффективны с точки зрения памяти.

Недостатком является то, что вы зависите от довольно сложного стороннего модуля. Но это очень хороший компромисс для многих целей.

Согласитесь с пятью колокольчиками, но вы также можете использовать Numpy, который является меньшим (более быстрый импорт) и более общей реализацией массива. (на самом деле, это зависимость от scipy). Это отличные инструменты, которые, как уже было сказано, «должны использовать», если вы имеете дело с такими манипуляциями.

Поздно к игре, и это не так хорошо, как некоторые из других, но я думал, что это было мило:

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

это слишком плохо, что sum(1,2,3) не работает. Если бы это было так, мы могли бы устранить там глупую lambda , но, полагаю, это затруднило бы распознать, какой из элементов (если таковой имеется) является «началом» суммы. Вы должны были бы изменить это только на ключевое слово, которое нарушило бы множество скриптов … О, хорошо. Думаю, мы просто будем жить с lambda .

[sum (a) для a в zip (* array)]

Мне нравится это. Мне нужно что-то связанное для перемежения объектов в список элементов, придумал что-то похожее, но более сжатое для четных списков длины:

 sum(zip(*array),()) 

например, перемежая два списка:

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

Вы можете просто сделать это:

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

Если вы хотите итерации по спискам таким образом, вы можете использовать chain модуля itertools :

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