`sum`是如何展开列表的?

37 投票
7 回答
88208 浏览
提问于 2025-04-15 23:28

一个像 l=[[1,2],[3,4]] 这样的多维列表可以通过 sum(l,[]) 转换成一维列表。这是怎么回事呢?

(对于更高维度的列表,这个方法不能直接使用,但可以重复使用来处理这些情况。比如,如果 A 是一个三维列表,那么 sum(sum(A),[]) 就可以把 A 转换成一维列表。)

7 个回答

4

对于任何类型的多维数组,这段代码可以将它们压缩成一维数组:

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 []
56

如果你的列表 nested 是你所说的“二维”的(也就是说你只想往下看一层,并且 nested 中所有一层的元素都是列表),那么我推荐你使用一个简单的列表推导式:

flat = [x for sublist in nested for x in sublist]

这种方法比用 sum 来求和要高效得多(sum 是用来处理数字的——它本来就不应该去处理非数字的求和,只是因为太麻烦了,所以没有阻止这种情况……我曾是 sum 在 Python 标准库中的最初提议者和第一个实现者,所以我想我应该知道这些;-)。

如果你想深入到“需要多深就多深”(也就是处理深层嵌套的列表),递归是最简单的方法,虽然如果不使用递归,你可以获得更高的性能(但这样会让事情变得更复杂)。

这个方法 提出了一个递归解决方案、一个去掉递归的方法,以及其他一些方法(这些都很有启发性,虽然没有我之前提到的那种一行代码的方法简单)。

48

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

撰写回答