在Python中合并/添加列表

35

我相信有更符合Python风格的方法 - 但我想不出来:如何将一个二维列表合并成一个一维列表?有点类似于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数组中的所有“行”是否具有相同的长度,可以被添加到彼此等等。有什么更好的方法可以做到这一点吗?

8个回答

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

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]

14

另一种方式:

map(sum, zip(*array))

8

如果你需要经常进行这种操作,你需要学习有关scipy的知识。

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

所有数组大小的检查都是自动完成的。求和使用纯C语言编写,所以非常快速。Scipy数组也非常内存高效。缺点是您依赖于一个相当复杂的第三方模块。但对于许多用途来说,这是一个非常好的折衷方案。

3

同意fivebells的观点,但你也可以使用Numpy,它是一个更小、更通用的类数组实现(实际上,它是scipy的一个依赖项)。这些都是很棒的工具,正如已经说过的那样,如果你处理这种操作,它们是“必须使用”的。


2
晚来了一步,这个答案不如其他一些答案好,但我认为它有点可爱:
map(lambda *x:sum(x),*array)

很遗憾sum(1,2,3)不起作用。如果它可以,我们就可以消除其中愚蠢的lambda,但我想这会使得区分哪个(如果有)元素是求和的“开始”变得困难。你必须将其更改为仅关键字参数,这将破坏许多脚本...好吧,我想我们只能接受lambda了。


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

嗯,虽然很有趣,但这并不是这个问题的答案(因此可能会吸引负评)。你可以举一个问题“如何交错几个列表?”并自己回答。也许使用一个使用超过两个列表的例子,否则有人会建议使用 ",".join(a) - Tim Pietzcker
同意Tim。这个“问答”与处理交错列表的线程相关,但被标记为此问题的重复!我在示例中使用了“,”只是为了简单起见,我的代码需要交错实际的用户定义类列表,但在抽象中很难解释。 - F1Rumors

0

你可以简单地这样做:

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

如果您希望以这种方式迭代列表,可以使用itertools模块的chain函数:
from itertools import chain

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接