【问题标题】:Python: Function to flatten generator containing another generatorPython:扁平化包含另一个生成器的生成器的函数
【发布时间】:2012-07-15 05:27:19
【问题描述】:

我想知道如何编写 python 函数,它可以展平生成器,生成另一个生成器或可迭代对象(也可以生成另一个生成器/可迭代对象......可能无限)。

示例如下:

gen(gen(1,2,3), gen(4,5,6), [7,8,9], [gen(10,11,12), gen(13,14,15)])

注意:gen - 表示生成器对象,gen 之后括号之间的内容是生成器 gen 产生的数据。

“扁平化”后的预期结果: gen(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)

flatten 函数也需要返回生成器! (否则,生成器的前面使用将毫无意义)。

请注意,我使用的是 python 3。

谢谢!

【问题讨论】:

    标签: python python-3.x generator


    【解决方案1】:

    最简单的方法是递归展平函数。假设您想深入到除字符串之外的每个可迭代对象,您可以这样做:

    def flatten(it):
        for x in it:
            if (isinstance(x, collections.Iterable) and
                not isinstance(x, str)):
                for y in flatten(x):
                    yield y
            else:
                yield x
    

    从 Python 3.3 开始,也可以写

    def flatten(it):
        for x in it:
            if (isinstance(x, collections.Iterable) and
                not isinstance(x, str)):
                yield from flatten(x)
            else:
                yield x
    

    【讨论】:

    • 非常感谢!通过我的尝试,我与您的尝试非常接近 :-) 问候!
    • +1 - 我一直忘记yield from,这是一个很好的提醒。
    • @JonClements:你“一直忘记”尚未发布的 Python 版本的功能?我很惊讶。 :)
    • 我的水晶球最近工作正常!? ;) [但严肃地说 - 我碰巧关注 PEP]
    【解决方案2】:

    非递归方法本质上是递归方法的展开,使用堆栈:

    def flatten(it):
        stack = []
        it = iter(it)
        while True:
            try:
                x = next(it)
            except StopIteration:
                if stack:
                    it = stack.pop()
                    continue
                else:
                    return
            if isinstance(x, collections.Iterable) and not isinstance(x, str):
                stack.append(it)
                it = iter(x)
            else:
                yield x
    

    【讨论】:

      猜你喜欢
      • 2019-06-15
      • 1970-01-01
      • 1970-01-01
      • 2018-12-11
      • 2020-10-10
      • 2021-12-28
      • 2011-12-19
      • 2016-12-16
      • 1970-01-01
      相关资源
      最近更新 更多