Python 3替换了不推荐使用的compiler.ast展平函数

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之前.

正如评论中所指出的那样,我认为这是核选项,并且可能会导致比它解决的更多问题.相反,最好的想法是让你的输出更加规则(例如,包含一个项目的输出仍然将它作为一个项目元组赋予它),并且在引入它的时候进行常规展平,而不是全部.

这将使代码更具逻辑性,可读性和易用性.当然,有些情况下你需要进行这种扁平化(如果数据来自某个你无法搞砸的地方,那么你别无选择,只能采用结构不合理的格式),在这种情况下,可能需要这种解决方案,但总的来说,这可能是一个坏主意.


daw*_*awg 5

您声明的函数采用嵌套列表并将其展平为新列表.

要将任意嵌套列表展平为新列表,可以按预期在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)