Mit*_*ops 10 python flatten python-3.x
>>> from compiler.ast import flatten
>>> flatten(["junk",["nested stuff"],[],[[]]])
['junk', 'nested stuff']
Run Code Online (Sandbox Code Playgroud)
我知道有一些堆栈溢出答案用于列表展平,但我希望pythonic,标准包,"一个,最好只有一个,显而易见的方法"来做到这一点.
Gar*_*tty 11
itertools.chain
是任何嵌套可迭代的一个级别的最佳解决方案 - 与任何纯python解决方案相比,它是高效的.
也就是说,它将适用于所有迭代,因此,如果你想避免它使字符串变平,则需要进行一些检查.
同样,它也不会神奇地变平到任意深度.也就是说,通常情况下,不需要这样的通用解决方案 - 相反,最好保持数据结构化,以便不需要以这种方式展平.
编辑:我认为如果必须进行任意展平,这是最好的方法:
import collections
def flatten(iterable):
for el in iterable:
if isinstance(el, collections.Iterable) and not isinstance(el, str):
yield from flatten(el)
else:
yield el
Run Code Online (Sandbox Code Playgroud)
记得basestring
在2.x中使用str
,而for subel in flatten(el): yield el
不是在yield from flatten(el)
3.3之前.
正如评论中所指出的那样,我认为这是核选项,并且可能会导致比它解决的更多问题.相反,最好的想法是让你的输出更加规则(例如,包含一个项目的输出仍然将它作为一个项目元组赋予它),并且在引入它的时候进行常规展平,而不是全部.
这将使代码更具逻辑性,可读性和易用性.当然,有些情况下你需要进行这种扁平化(如果数据来自某个你无法搞砸的地方,那么你别无选择,只能采用结构不合理的格式),在这种情况下,可能需要这种解决方案,但总的来说,这可能是一个坏主意.
您声明的函数采用嵌套列表并将其展平为新列表.
要将任意嵌套列表展平为新列表,可以按预期在Python 3上运行:
import collections
def flatten(x):
result = []
for el in x:
if isinstance(x, collections.Iterable) and not isinstance(el, str):
result.extend(flatten(el))
else:
result.append(el)
return result
print(flatten(["junk",["nested stuff"],[],[[]]]))
Run Code Online (Sandbox Code Playgroud)
打印:
['junk', 'nested stuff']
Run Code Online (Sandbox Code Playgroud)
如果你想要一个做同样事情的发电机:
def flat_gen(x):
def iselement(e):
return not(isinstance(e, collections.Iterable) and not isinstance(e, str))
for el in x:
if iselement(el):
yield el
else:
for sub in flat_gen(el): yield sub
print(list(flat_gen(["junk",["nested stuff"],[],[[[],['deep']]]])))
# ['junk', 'nested stuff', 'deep']
Run Code Online (Sandbox Code Playgroud)
对于Python 3.3及更高版本,请使用yield而不是循环:
def flat_gen(x):
def iselement(e):
return not(isinstance(e, collections.Iterable) and not isinstance(e, str))
for el in x:
if iselement(el):
yield el
else:
yield from flat_gen(el)
Run Code Online (Sandbox Code Playgroud)