平Flatten不规则(任意嵌套)列表
是的,我知道这个话题之前已经讨论过了:
不过据我所知,除了一个解决方案,其他的都无法处理像 [[[1, 2, 3], [4, 5]], 6]
这样的列表,而我们想要的输出是 [1, 2, 3, 4, 5, 6]
(或者更好的是,得到一个迭代器)。
我看到的唯一一个能处理任意嵌套的解决方案在 这个问题中:
def flatten(x):
result = []
for el in x:
if hasattr(el, "__iter__") and not isinstance(el, basestring):
result.extend(flatten(el))
else:
result.append(el)
return result
这是最好的方法吗?我有没有遗漏什么?有没有什么问题?
53 个回答
49
使用递归和鸭子类型的生成器(已更新为Python 3):
def flatten(L):
for item in L:
try:
yield from flatten(item)
except TypeError:
yield item
list(flatten([[[1, 2, 3], [4, 5]], 6]))
>>>[1, 2, 3, 4, 5, 6]
68
我的解决方案:
import collections
def flatten(x):
if isinstance(x, collections.Iterable):
return [a for i in x for a in flatten(i)]
else:
return [x]
这个方法稍微简洁一点,但基本上是一样的。
477
使用生成器函数可以让你的代码更容易阅读,同时也能提高性能。
Python 2
在Python 2.6中,添加了Iterable
ABC:
from collections import Iterable
def flatten(xs):
for x in xs:
if isinstance(x, Iterable) and not isinstance(x, basestring):
for item in flatten(x):
yield item
else:
yield x
Python 3
在Python 3中,basestring
不再使用了,但可以用元组 (str, bytes)
达到相同的效果。此外,yield from
操作符可以一次从生成器中返回一个项目。
from collections.abc import Iterable
def flatten(xs):
for x in xs:
if isinstance(x, Iterable) and not isinstance(x, (str, bytes)):
yield from flatten(x)
else:
yield x