是一个简短的语法连接列表列表到一个单一的列表(或迭代器)在python?
例如,我有一个列表,如下所示,我想迭代a,b和c。
x = [["a","b"], ["c"]]
我能想到的最好的是如下。
result = []
[ result.extend(el) for el in x]
for el in result:
print el
是一个简短的语法连接列表列表到一个单一的列表(或迭代器)在python?
例如,我有一个列表,如下所示,我想迭代a,b和c。
x = [["a","b"], ["c"]]
我能想到的最好的是如下。
result = []
[ result.extend(el) for el in x]
for el in result:
print el
当前回答
性能比较:
import itertools
import timeit
big_list = [[0]*1000 for i in range(1000)]
timeit.repeat(lambda: list(itertools.chain.from_iterable(big_list)), number=100)
timeit.repeat(lambda: list(itertools.chain(*big_list)), number=100)
timeit.repeat(lambda: (lambda b: map(b.extend, big_list))([]), number=100)
timeit.repeat(lambda: [el for list_ in big_list for el in list_], number=100)
[100*x for x in timeit.repeat(lambda: sum(big_list, []), number=1)]
生产:
>>> import itertools
>>> import timeit
>>> big_list = [[0]*1000 for i in range(1000)]
>>> timeit.repeat(lambda: list(itertools.chain.from_iterable(big_list)), number=100)
[3.016212113769325, 3.0148865239060227, 3.0126415732791028]
>>> timeit.repeat(lambda: list(itertools.chain(*big_list)), number=100)
[3.019953987082083, 3.528754223385439, 3.02181439266457]
>>> timeit.repeat(lambda: (lambda b: map(b.extend, big_list))([]), number=100)
[1.812084445152557, 1.7702404451095965, 1.7722977998725362]
>>> timeit.repeat(lambda: [el for list_ in big_list for el in list_], number=100)
[5.409658160700605, 5.477502077679354, 5.444318360412744]
>>> [100*x for x in timeit.repeat(lambda: sum(big_list, []), number=1)]
[399.27587954973444, 400.9240571138051, 403.7521153804846]
这是在Windows XP 32位的Python 2.7.1上,但上面评论中的@temoto得到from_iterable比map+extend更快,所以它相当依赖于平台和输入。
不要使用sum(big_list, [])
其他回答
对于无限嵌套的元素,这是递归工作的:
def iterFlatten(root):
if isinstance(root, (list, tuple)):
for element in root:
for e in iterFlatten(element):
yield e
else:
yield root
结果:
>>> b = [["a", ("b", "c")], "d"] >>> list(iterFlatten(b)) ['a', 'b', 'c', 'd']
性能比较:
import itertools
import timeit
big_list = [[0]*1000 for i in range(1000)]
timeit.repeat(lambda: list(itertools.chain.from_iterable(big_list)), number=100)
timeit.repeat(lambda: list(itertools.chain(*big_list)), number=100)
timeit.repeat(lambda: (lambda b: map(b.extend, big_list))([]), number=100)
timeit.repeat(lambda: [el for list_ in big_list for el in list_], number=100)
[100*x for x in timeit.repeat(lambda: sum(big_list, []), number=1)]
生产:
>>> import itertools
>>> import timeit
>>> big_list = [[0]*1000 for i in range(1000)]
>>> timeit.repeat(lambda: list(itertools.chain.from_iterable(big_list)), number=100)
[3.016212113769325, 3.0148865239060227, 3.0126415732791028]
>>> timeit.repeat(lambda: list(itertools.chain(*big_list)), number=100)
[3.019953987082083, 3.528754223385439, 3.02181439266457]
>>> timeit.repeat(lambda: (lambda b: map(b.extend, big_list))([]), number=100)
[1.812084445152557, 1.7702404451095965, 1.7722977998725362]
>>> timeit.repeat(lambda: [el for list_ in big_list for el in list_], number=100)
[5.409658160700605, 5.477502077679354, 5.444318360412744]
>>> [100*x for x in timeit.repeat(lambda: sum(big_list, []), number=1)]
[399.27587954973444, 400.9240571138051, 403.7521153804846]
这是在Windows XP 32位的Python 2.7.1上,但上面评论中的@temoto得到from_iterable比map+extend更快,所以它相当依赖于平台和输入。
不要使用sum(big_list, [])
总是有reduce(不推荐使用functools):
>>> x = [ [ 'a', 'b'], ['c'] ]
>>> for el in reduce(lambda a,b: a+b, x, []):
... print el
...
__main__:1: DeprecationWarning: reduce() not supported in 3.x; use functools.reduce()
a
b
c
>>> import functools
>>> for el in functools.reduce(lambda a,b: a+b, x, []):
... print el
...
a
b
c
>>>
不幸的是,用于列表连接的加号操作符不能用作函数——或者幸运的是,如果为了提高可见性,您希望lambdas变得更丑一些。
如果你需要一个列表,而不是一个生成器,使用list():
from itertools import chain
x = [["a","b"], ["c"]]
y = list(chain(*x))
您所描述的就是所谓的将列表扁平化,有了这些新知识,您将能够在谷歌上找到许多解决方案(没有内置的扁平化方法)。以下是其中一个,来自http://www.daniel-lemire.com/blog/archives/2006/05/10/flattening-lists-in-python/:
def flatten(x):
flat = True
ans = []
for i in x:
if ( i.__class__ is list):
ans = flatten(i)
else:
ans.append(i)
return ans