展平嵌套的生成器表达式

cas*_*avo 9 python generator python-itertools

我试图压扁嵌套的发电机发电机,但我得到了一个意想不到的结果:

>>> g = ((3*i + j for j in range(3)) for i in range(3))
>>> list(itertools.chain(*g))
[6, 7, 8, 6, 7, 8, 6, 7, 8]
Run Code Online (Sandbox Code Playgroud)

我希望结果看起来像这样:

[0, 1, 2, 3, 4, 5, 6, 7, 8]
Run Code Online (Sandbox Code Playgroud)

我想我得到了意想不到的结果,因为内部生成器在外部生成器已被迭代之前没有被评估,设置i为2.我可以通过使用列表推导强制评估内部生成器来解决一个解决方案生成器表达式:

>>> g = ([3*i + j for j in range(3)] for i in range(3))
>>> list(itertools.chain(*g))
[0, 1, 2, 3, 4, 5, 6, 7, 8]
Run Code Online (Sandbox Code Playgroud)

理想情况下,我想要一个完全懒惰的解决方案,并且在使用之前不会强制评估内部嵌套元素.

有没有办法压缩任意深度的嵌套生成器表达式(可能使用其他东西itertools.chain)?

编辑:

不,我的问题不是类中生成器中变量范围的重复.老实说,我不知道这两个问题是如何相关的.也许主持人可以解释为什么他认为这是重复的.

此外,我的问题的两个答案都是正确的,因为它们可以用来编写一个正确展平嵌套生成器的函数.

def flattened1(iterable):
    iter1, iter2 = itertools.tee(iterable)
    if isinstance(next(iter1), collections.Iterable):
        return flattened1(x for y in iter2 for x in y)
    else:
        return iter2

def flattened2(iterable):
    iter1, iter2 = itertools.tee(iterable)
    if isinstance(next(iter1), collections.Iterable):
        return flattened2(itertools.chain.from_iterable(iter2))
    else:
        return iter2
Run Code Online (Sandbox Code Playgroud)

据我所知timeit,他们都表现得相同.

>>> timeit(test1, setup1, number=1000000)
18.173431718023494
>>> timeit(test2, setup2, number=1000000)
17.854709611972794
Run Code Online (Sandbox Code Playgroud)

从风格的角度来看,我也不确定哪一个更好,因为x for y in iter2 for x in y它有点像脑筋急转弯,但可以说更优雅itertools.chain.from_iterable(iter2).感谢投入.

遗憾的是,我只能将两个同样好的答案之一标记为正确.

DSM*_*DSM 10

chain(*g)您可以使用chain.from_iterable以下代码而不是使用:

>>> g = ((3*i + j for j in range(3)) for i in range(3))
>>> list(itertools.chain(*g))
[6, 7, 8, 6, 7, 8, 6, 7, 8]
>>> g = ((3*i + j for j in range(3)) for i in range(3))
>>> list(itertools.chain.from_iterable(g))
[0, 1, 2, 3, 4, 5, 6, 7, 8]
Run Code Online (Sandbox Code Playgroud)


bla*_*ite 6

这个怎么样:

[x for y in g for x in y]
Run Code Online (Sandbox Code Playgroud)

产生:

[0, 1, 2, 3, 4, 5, 6, 7, 8]
Run Code Online (Sandbox Code Playgroud)