接受PEP 448
在Python 3.5
引入了额外的拆包概括。
例如:
>>> l1 = [1, 2, 3]
>>> l2 = [4, 5, 6]
# unpack both iterables in a list literal
>>> joinedList = [*l1, *l2]
>>> print(joinedList)
[1, 2, 3, 4, 5, 6]
问题:有没有办法用列表列表做类似的事情?
此代码不起作用:
SyntaxError:迭代解包不能用于理解
# List of variable size
list_of_lists = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
joined_list = [*l for l in list_of_lists]
当然,您可以执行以下操作,但看起来不那么优雅且看起来效率不高:
# List of variable size
list_of_lists = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
joined_list = list()
for l in list_of_lists:
joined_list += l
去上学怎么样:sum()
joined_list = sum(list_of_lists, [])
# List of variable size
list_of_lists = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
joined_list = sum(list_of_lists, [])
print(joined_list)
[1, 2, 3, 4, 5, 6, 7, 8, 9]
我会劝阻在这里使用sum
,因为它是Schlemiel the Painter's algorithm的一种形式。 sum
实际上禁止与str
;他们没有试图阻止所有的序列使用,以避免减缓sum
试图阻止每一次滥用,但它仍然是一个坏主意。
问题在于,这意味着你每次都要逐渐建立更大的临时list
s,通过复制你目前所见的所有内容,以及一遍又一遍的新内容,在构建下一个临时版本之后丢弃最后一个临时版本。如果第一个列表中有一百万个项目,并且还有十个list
s要连接到它上面,那么你要复制至少1000万个元素(即使其他十个list
s是空的)。您的原始代码实际上更好,因为使用+=
运算符执行就地扩展,保持O(n)
(对于所有n
s的list
元素)范围的最坏情况性能,而不是O(n*m)
(对于n
m
s的list
元素)。
它还有一个只适用于一种类型的问题;如果一些输入是list
s,一些tuple
s和一些生成器,sum
将不起作用(因为list.__add__
将不接受另一方的非list
操作数)。
所以不要这样做。这是what itertools.chain
and it's alternate constructor, itertools.chain.from_iterable
were made for:
from itertools import chain
list_of_lists = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
joined_list = list(chain.from_iterable(list_of_lists))
它保证O(n)
,适用于您抛出的任何迭代,等等。
是的,很明显,如果你只有三个元素的三个list
s,它几乎不重要。但是如果输入迭代的大小或迭代的数量是任意大的,或者类型不一致,chain
将起作用,sum
将不会。