在这个问题的评论讨论中提到,虽然将一系列字符串连接起来只需使用
''.join([str1, str2, ...])
,但是连接一系列列表则可以使用像list(itertools.chain(lst1, lst2, ...))
这样的方法,尽管你也可以使用类似于[x for y in [lst1, lst2, ...] for x in y]
的列表解析式。令人惊讶的是,第一种方法始终比第二种方法更快。import random
import itertools
random.seed(100)
lsts = [[1] * random.randint(100, 1000) for i in range(1000)]
%timeit [x for y in lsts for x in y]
# 39.3 ms ± 436 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit list(itertools.chain.from_iterable(lsts))
# 30.6 ms ± 866 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit list(x for y in lsts for x in y) # Proposed in comments
# 62.5 ms ± 504 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
# Loop-based methods proposed in the comments
%%timeit
a = []
for lst in lsts: a += lst
# 26.4 ms ± 634 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
%%timeit
a = []
for lst in lsts: a.extend(lst)
# 26.7 ms ± 728 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
虽然并非数量级的差异,但也不可忽略。我在想可能是怎么回事,因为列表理解通常是解决给定问题的最快方法之一。起初,我认为也许itertools.chain
对象会有一个len
,list
构造函数可以使用它来预分配必要的内存,但事实并非如此(无法在itertools.chain
对象上调用len
)。是否以某种方式进行了自定义的itertools.chain
到list
转换,或者itertools.chain
利用了其他机制?
在Windows 10 x64上测试了Python 3.6.3,如果有关联。
编辑:
看来最快的方法毕竟是对每个列表调用空列表的.extend
方法,就像@zwer提出的那样,这可能是因为它按“块”而不是按单个元素处理数据。
list(x for y in lsts for x in y)
表达的意思是什么? - Peter Wood