如何从列表推导式获取扁平化结果而非嵌套列表?
我有一个列表 A
,还有一个函数 f
,这个函数可以接收 A
中的一个元素,并返回一个列表。我可以用列表推导式把 A
中的每个元素都处理一遍,比如 [f(a) for a in A]
,但这样会得到一个列表的列表。假设我的输入是 [a1,a2,a3]
,结果就会是 [[b11,b12],[b21,b22],[b31,b32]]
。
我该怎么做才能得到一个“扁平化”的列表 [b11,b12,b21,b22,b31,b32]
呢?换句话说,在 Python 中,怎么才能实现类似于函数式编程语言中的 flatmap
,或者 .NET 中的 SelectMany
呢?
(在实际代码中,A
是一个目录的列表,而 f
是 os.listdir
。我想要构建一个包含所有子目录的扁平列表。)
另见: 如何将列表的列表变成扁平列表? 这是关于在创建后扁平化列表的一般问题。
18 个回答
73
你可以在itertools
的使用示例中找到一个很好的答案:
import itertools
def flatten(list_of_lists):
return list(itertools.chain.from_iterable(list_of_lists))
96
>>> from functools import reduce # not needed on Python 2
>>> list_of_lists = [[1, 2],[3, 4, 5], [6]]
>>> reduce(list.__add__, list_of_lists)
[1, 2, 3, 4, 5, 6]
这个 itertools
的解决方案 更高效,但这个方法看起来更符合 Python 的风格。
165
你可以在一个列表推导式中使用嵌套循环:
[filename for path in dirs for filename in os.listdir(path)]
这在功能上是等价于:
filenames = []
for path in dirs:
for filename in os.listdir(path):
filenames.append(filename)