35

我很确定应该有一种更 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 数组中的所有“线”是否具有相同的长度,是否可以相互添加等等。还有什么更好的方法呢?

4

8 回答 8

71
[sum(a) for a in zip(*array)]
于 2008-11-04T21:16:39.117 回答
63

[sum(value) for value in 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]
于 2008-11-04T21:33:47.257 回答
14

另一种方法:

map(sum, zip(*array))
于 2008-11-05T15:31:04.087 回答
8

如果您正在做很多此类事情,那么您想了解scipy.

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

系统会自动为您检查所有数组大小。求和是用纯 C 语言完成的,所以速度非常快。 scipy数组也非常节省内存。

缺点是您依赖于相当复杂的第三方模块。但这对于许多目的来说是一个很好的权衡。

于 2008-11-05T15:24:08.983 回答
3

同意 Fivebells,但您也可以使用 Numpy,它是一个更小(更快的导入)和更通用的类似数组的东西的实现。(其实是scipy的依赖)。如前所述,这些都是很棒的工具,如果您处理这种操作,它们是“必须使用的”。

于 2011-02-25T04:45:31.813 回答
2

游戏迟到了,它的答案不如其他一些好,但我认为它有点可爱:

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

太糟糕了,sum(1,2,3)这不起作用。如果确实如此,我们可以消除其中的愚蠢lambda,但我认为这将难以辨别哪些元素(如果有)是总和的“开始”。您必须将其更改为仅关键字的争论,这会破坏很多脚本……哦,好吧。我想我们只会住在一起lambda

于 2012-11-05T21:04:10.277 回答
0

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

我喜欢。我需要一些与将对象交错到项目列表中相关的东西,想出了一些类似但更简洁的甚至长度列表:

sum(zip(*array),())

例如,交错两个列表:

a = [1,2,3]
b = ['a','b','c']
sum(zip(a,b),())
(1, 'a', 2, 'b', 3, 'c')
于 2015-04-03T13:55:00.377 回答
0

你可以简单地这样做:

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

如果您希望以这种方式遍历列表,可以使用chainitertools模块:

from itertools import chain

for x in array.chain.from_iterable(zip(*array)):
    print x   
# prints 1, 4, 7, 2, 5, 8, ...
于 2015-04-03T21:02:37.843 回答