python - itertools.chain() 的广度优先版本

标签 python python-itertools

itertools 中有 chain,它将多个生成器组合成一个,本质上对它们进行深度优先迭代,即 chain。 from_iterable(['ABC', '123']) 产生 A、B、C、1、2、3。但是,没有广度优先版本,还是我遗漏了什么?当然有 izip_longest,但是对于大量的生成器来说这感觉很尴尬,因为元组会很长而且可能非常稀疏。

我想到了以下内容:

def chain_bfs(*generators):
    generators = list(generators)
    while generators:
        g = generators.pop(0)
        try:
            yield g.next()
        except StopIteration:
            pass
        else:
            generators.append(g)

我觉得有点冗长,我是否缺少更 Pythonic 的方法?这个函数是否适合包含在 itertools 中?

最佳答案

你可以使用 collections.deque()通过你的迭代器旋转;旋转双端队列效率更高。我也将其称为链式 zipper ,而不是“呼吸链”,如下所示:

from collections import deque

def chained_zip(*iterables):
    iterables = deque(map(iter, iterables))
    while iterables:
        try:
            yield next(iterables[0])
        except StopIteration:
            iterables.popleft()
        else:
            iterables.rotate(-1)

演示:

>>> list(chained_zip('ABC', '123'))
['A', '1', 'B', '2', 'C', '3']
>>> list(chained_zip('AB', '1234'))
['A', '1', 'B', '2', '3', '4']

还有一个roundrobin() recipe in the documentation做同样的事情,使用 itertools.cycle() function :

def roundrobin(*iterables):
    "roundrobin('ABC', 'D', 'EF') --> A D E B F C"
    # Recipe credited to George Sakkis
    pending = len(iterables)
    nexts = cycle(iter(it).__next__ for it in iterables)
    while pending:
        try:
            for next in nexts:
                yield next()
        except StopIteration:
            pending -= 1
            nexts = cycle(islice(nexts, pending))

关于python - itertools.chain() 的广度优先版本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23874228/

相关文章:

python - wxpython 没有 'adv'

python - 成员每组出现一次的唯一对组

python - 是否有 `itemgetter` 等效于 `numpy.ndarray` ?

python - 如何在具有不同 Y 轴的同一 seaborn 图中很好地制作条形图和线图?

python - 检查小部件是否存在(Tkinter)

python - 从 Python 中的生成器获取多个单独的值

python - 如何计算从 1 到 N 的一系列数字的所有可能组合的数量?

python - 在 Python 中创建两组列表的所有组合

python - 从现有列表创建较小的列表

python - 在字典中递增