从Python列表中列出一个扁平列表
我想知道是否有一个快捷方式可以在Python列表中列出一个简单的列表。
我可以在for循环中做到这一点,但也许有一些很酷的“单线程”? 我尝试减少,但我得到一个错误。
码
l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
reduce(lambda x, y: x.extend(y), l)
错误信息
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <lambda>
AttributeError: 'NoneType' object has no attribute 'extend'
flat_list = [item for sublist in l for item in sublist]
意思是:
for sublist in l:
for item in sublist:
flat_list.append(item)
比迄今发布的捷径要快。 ( l
是要变平的列表。)
这是一个相应的功能:
flatten = lambda l: [item for sublist in l for item in sublist]
作为证据,一如既往,您可以在标准库中使用timeit
模块:
$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' '[item for sublist in l for item in sublist]'
10000 loops, best of 3: 143 usec per loop
$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'sum(l, [])'
1000 loops, best of 3: 969 usec per loop
$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'reduce(lambda x,y: x+y,l)'
1000 loops, best of 3: 1.1 msec per loop
说明:当存在L个子列表时,基于+
(包括sum
的隐含用法)的快捷方式必然是O(L**2)
- 随着中间结果列表不断变长,每一步都有一个新的中间结果列表对象被分配,并且之前中间结果中的所有项目都必须被复制(以及最后添加的几个新项目)。 因此(为了简单起见,并没有实际的通用性丧失),假设你有每个I项的L子列表:第一个I项被来回复制L-1次,第二个I项L-2次,等等; 拷贝总数是I的倍数,x是从1到L排除的x,即I * (L**2)/2
。
列表理解只会生成一个列表,并且每个项目(从其原始的居住地点到结果列表)也只是一次。
你可以使用itertools.chain()
:
>>> import itertools
>>> list2d = [[1,2,3],[4,5,6], [7], [8,9]]
>>> merged = list(itertools.chain(*list2d))
或者,在Python> = 2.6中,使用itertools.chain.from_iterable()
,它不需要解包列表:
>>> import itertools
>>> list2d = [[1,2,3],[4,5,6], [7], [8,9]]
>>> merged = list(itertools.chain.from_iterable(list2d))
这种方法可以说比[item for sublist in l for item in sublist]
更可读,并且似乎也更快:
[me@home]$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99;import itertools' 'list(itertools.chain.from_iterable(l))'
10000 loops, best of 3: 24.2 usec per loop
[me@home]$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' '[item for sublist in l for item in sublist]'
10000 loops, best of 3: 45.2 usec per loop
[me@home]$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'sum(l, [])'
1000 loops, best of 3: 488 usec per loop
[me@home]$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'reduce(lambda x,y: x+y,l)'
1000 loops, best of 3: 522 usec per loop
[me@home]$ python --version
Python 2.7.3
作者注意 :这是低效的。 但很有趣,因为monad很棒。 它不适合生产Python代码。
>>> sum(l, [])
[1, 2, 3, 4, 5, 6, 7, 8, 9]
这只是对第一个参数传递的iterable的元素进行求和,将第二个参数作为sum的初始值(如果没有给出,则使用0
代替,这种情况会给出错误)。
由于sum([[1,3],[2,4]],[])
的结果实际上得到了[1,3]+[2,4]
,这等于[1,3,2,4]
。
请注意,只适用于列表清单。 对于列表清单列表,您需要另一个解决方案。
链接地址: http://www.djcxy.com/p/3129.html