【问题标题】:How do I create a generator within a generator- Python如何在生成器中创建生成器 - Python
【发布时间】:2018-12-18 18:51:35
【问题描述】:

如果我创建了一个列表:

_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

并尝试使用生成器获取每个值<= 6:

test = next(i for i in a for a in _list if i <= 6)

(顺便说一句,这不起作用↑↑↑↑↑)

如何使用生成器遍历列表中的列表?如果这是不可能的,我可以用什么方法来代替它?

我看过这里: python generator of generators?,但是找不到答案...

【问题讨论】:

  • 你为什么不使用列表推导?

标签: python generator


【解决方案1】:

使用来自内置模块itertoolschain

from itertools import chain

_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

print(list(i for i in chain.from_iterable(_list) if i <= 6))

输出:

[1, 2, 3, 4, 5, 6]

itertools.chain 做什么?根据manual pages

创建一个迭代器,从第一个可迭代对象中返回元素,直到 它被耗尽,然后继续下一个迭代,直到所有的 可迭代对象已用尽。用于将连续序列视为 单序列。

【讨论】:

  • 如果我想找到每个输出的索引,我该怎么做?
  • @flameboi 您可以索引结果列表:例如list(i for i in chain.from_iterable(_list) if i &lt;= 6)[0]
  • @Andrej 这是什么意思?我不明白。
  • 为了澄清,在我的第一条评论中,我问是否有办法输出 [0][0]1 例如。
  • @flameboi 你的意思是print(_list[0][0])
【解决方案2】:

在这种情况下,您不需要创建生成器的生成器。只需在一个生成器中创建一个双循环(以展平列表,然后测试元素值):

_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

gen = (x for sublist in _list for x in sublist if x <= 6)

这种双重for 理解语法需要一些使用,理解通常写成“反过来”,但不是在循环的情况下,因此你会感到困惑。更一般的形式是:

(expression(item) for sublist in input_list for item in sublist if condition(item))

然后获取第一个匹配的元素:

print(next(gen,None))  # None is printed if there's no matching element

(要获取所有元素,当然您必须在 gen 上进行迭代,next 提供“下一个”值,就像您在生成器上“手动”迭代一样)

【讨论】:

    【解决方案3】:

    要将两个 fors 嵌套在同一个生成器中,您必须颠倒顺序

    test = next(i for a in _list for i in a if i <= 6)
    

    【讨论】:

    • 当我打印test时,它输出1。它不应该输出1, 2, 3, 4, 5, 6吗?
    • @flameboi next() 只获取下一个元素。如果您希望所有元素都使用list() 来完全使用生成器:test = list(i for a in _list for i in a if i &lt;= 6)(此时您可以使用列表推导式,它总是返回一个列表)
    【解决方案4】:

    您可以结合 itertools.takewhileitertools.chain 来创建符合您要求的迭代器

    >>> from itertools import chain, takewhile
    >>> itr = takewhile(lambda i: i<=6, chain(*_list))
    >>> print (list(itr))
    [1, 2, 3, 4, 5, 6]
    

    【讨论】:

      【解决方案5】:
      >>> t = (i for a in _list for i in a if i <= 6)
      >>> next(t)
      1
      >>> next(t)
      2
      >>> next(t)
      3
      >>> next(t)
      4
      >>> next(t)
      5
      >>> 
      

      使用list将迭代器转换为列表

      >>> t = (i for a in _list for i in a if i <= 6)
      >>> list(t)
      [1, 2, 3, 4, 5, 6]
      

      【讨论】:

        猜你喜欢
        • 2017-05-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-10-30
        • 2013-10-02
        • 1970-01-01
        • 2010-10-16
        • 2013-04-20
        相关资源
        最近更新 更多