python - 转置嵌套生成器

标签 python

是否有一种明确的方法来迭代列表中每个生成器的项目?我相信展示问题本质的最简单方法是举一个例子。在这里

0。假设我们有一个返回生成器的函数:

def gen_fun(hint):
    for i in range(1,10):
        yield "%s %i" % (hint, i)

1。具有直接迭代顺序的清晰解决方案:

hints = ["a", "b", "c"]
for hint in hints:
    for  txt in gen_fun(hint):
        print(txt)

这会打印

a 1
a 2
a 3
...
b 1
b 2
b 3
...

2。具有反向迭代顺序的麻烦解决方案

hints = ["a", "b", "c"]
generators = list(map(gen_fun, hints))
any = True
while any:
    any = False
    for g in generators:
        try:
            print(next(g))
            any = True
        except StopIteration:
            pass

这会打印

a 1
b 1
c 1
a 2
b 2
...

这按预期工作并且达到了我想要的效果。

奖励积分:

相同的任务,但 gen_fun 范围可能不同,即

def gen_fun(hint):
    if hint == 'a':
        m = 5
    else:
        m = 10
    for i in range(1,m):
        yield "%s %i" % (hint, i)

本例的正确输出是:

a 1
b 1
c 1
a 2
b 2
c 2
a 3
b 3
c 3
a 4
b 4
c 4
b 5
c 5
b 6
c 6
b 7
c 7
b 8
c 8
b 9
c 9

问题:

有没有办法实现情况2清理器?

最佳答案

如果我正确理解了这个问题,您可以使用 zip() 来实现与整个 while any 循环相同的效果:

hints = ["a", "b", "c"]
generators = list(map(gen_fun, hints))
for x in zip(*generators):
    for txt in x:
        print(txt)

输出:

a 1
b 1
c 1
a 2
b 2
...

更新:

如果生成器的长度不同,请将它们全部“压缩”到最短。您可以使用itertools.izip_longest (如 this q/a 建议)以实现相反的行为并继续屈服,直到最长的生成器耗尽。不过,您需要过滤掉填充的值:

hints = ["a", "b", "c"]
generators = list(map(gen_fun, hints))
for x in zip_longest(*generators):
    for txt in x:
        if txt:
            print(txt)

关于python - 转置嵌套生成器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33699885/

相关文章:

python - 如何使用 SqlAlchemy_Utils ChoiceType 设置默认值

python - 使用 Python 沿列插入二维矩阵

python - 通过匹配值python删除键值对

python gevent : unexpected output in KeyboardInterrupt

python - 小数精度越高,每个实例是否使用更多内存?

python - 如何在 SQLAlchemy 查询中获取列名?

Python 和 openpyxl - 更改列宽以适应?

python - 使用 .bat 文件启动带有 venv 的 flask

python - 我如何让 Python 的负面回顾不那么贪婪?

python - 为 requests.Session() 对象设置主机和端口