我很确定应该有更多的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阵列中的所有“线”是否具有相同的长度,可以相互添加等等。有什么更好的方法呢?
答案 0 :(得分:70)
[sum(a) for a in zip(*array)]
答案 1 :(得分:63)
[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]
答案 2 :(得分:14)
另一种方式:
map(sum, zip(*array))
答案 3 :(得分:8)
如果你做了很多这类事情,你想了解scipy
.
>>> import scipy
>>> sum(scipy.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]))
array([12, 15, 18])
自动检查所有数组大小。总和是用纯C完成的,所以它非常快。 scipy
数组也非常有效。
缺点是你依赖于相当复杂的第三方模块。但对于许多目的而言,这是一个非常好的权衡。
答案 4 :(得分:3)
同意fivebells,但你也可以使用Numpy,这是一个更小(更快的导入)和类似数组的东西的更通用的实现。 (实际上,它是scipy的依赖)。如果您处理这种操作,这些都是很好的工具,如前所述,它们是“必须使用的”。
答案 5 :(得分:2)
游戏的后期,它并不像其他人那样好,但我觉得它很可爱:
map(lambda *x:sum(x),*array)
sum(1,2,3)
不起作用太糟糕了。如果确实如此,我们可以消除那里的愚蠢lambda
,但我认为这将使得难以辨别哪些(如果有的话)元素是总和的“开始”。你必须把它改成一个关键词只有争论会打破很多脚本......哦。我想我们只会和lambda
一起生活。
答案 6 :(得分:0)
[in(a)for a zip(* array)]
我喜欢那样。我需要将对象交错到项目列表中的相关内容,想出类似的东西,但对于偶数长度列表更简洁:
sum(zip(*array),())
例如,交错两个列表:
a = [1,2,3]
b = ['a','b','c']
sum(zip(a,b),())
(1, 'a', 2, 'b', 3, 'c')
答案 7 :(得分:0)
你可以这样做:
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, ...