从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

上一篇: Making a flat list out of list of lists in Python

下一篇: Getting the last element of a list in Python