`sum`是如何展开列表的?
一个像 l=[[1,2],[3,4]]
这样的多维列表可以通过 sum(l,[])
转换成一维列表。这是怎么回事呢?
(对于更高维度的列表,这个方法不能直接使用,但可以重复使用来处理这些情况。比如,如果 A 是一个三维列表,那么 sum(sum(A),[])
就可以把 A 转换成一维列表。)
7 个回答
对于任何类型的多维数组,这段代码可以将它们压缩成一维数组:
def flatten(l):
try:
return flatten(l[0]) + (flatten(l[1:]) if len(l) > 1 else []) if type(l) is list else [l]
except IndexError:
return []
如果你的列表 nested
是你所说的“二维”的(也就是说你只想往下看一层,并且 nested
中所有一层的元素都是列表),那么我推荐你使用一个简单的列表推导式:
flat = [x for sublist in nested for x in sublist]
这种方法比用 sum
来求和要高效得多(sum
是用来处理数字的——它本来就不应该去处理非数字的求和,只是因为太麻烦了,所以没有阻止这种情况……我曾是 sum
在 Python 标准库中的最初提议者和第一个实现者,所以我想我应该知道这些;-)。
如果你想深入到“需要多深就多深”(也就是处理深层嵌套的列表),递归是最简单的方法,虽然如果不使用递归,你可以获得更高的性能(但这样会让事情变得更复杂)。
这个方法 提出了一个递归解决方案、一个去掉递归的方法,以及其他一些方法(这些都很有启发性,虽然没有我之前提到的那种一行代码的方法简单)。
sum
是用 +
这个符号把一系列数字加在一起的。比如说 sum([1,2,3]) == 6
,就是把 1、2 和 3 加起来等于 6。第二个参数是可选的起始值,默认是 0。比如 sum([1,2,3], 10) == 16
,这里就是在 10 的基础上再加上 1、2 和 3。
在你的例子中,它做的是 [] + [1,2] + [3,4]
,这里的 +
是把两个列表合并在一起。因此结果是 [1,2,3,4]
。
空列表作为 sum
的第二个参数是必须的,因为如上所述,sum
默认是从 0 开始加的(也就是 0 + [1,2] + [3,4]
),这样会导致错误:不支持的操作类型:'int' 和 'list'。
这是 sum
的帮助文档中相关的部分:
sum(sequence[, start]) -> value
返回一系列数字(不是字符串)的总和,加上参数 'start' 的值(默认是 0)。
注意
正如 wallacoloo 所评论的,这不是一个通用的解决方案来处理任何多维列表。它只适用于一维列表的列表,因为上面提到的行为。
更新
如果你想要处理一层嵌套的列表,可以参考 itertools 页面上的这个方法:
def flatten(listOfLists):
"Flatten one level of nesting"
return chain.from_iterable(listOfLists)
如果你想要处理更深层嵌套的列表(包括不规则嵌套的列表),可以查看 这个问题 的 被接受的答案(还有一些其他相关的问题链接在那个问题里)。
注意,这个方法返回的是一个 itertools.chain
对象(可以迭代),而另一个问题的答案返回的是一个 generator
对象,所以如果你想要得到完整的列表,而不是逐个迭代,就需要把它们包裹在 list
的调用中。例如 list(flatten(my_list_of_lists))
。