如何合并多个迭代器以获得一个新的迭代器,该迭代器将随机迭代它们?

4
假设我有一组迭代器列表:
iterators = [ iter([2, 3, 4]), iter([7, 9]), iter([-1, -2, -3, -4]) ]

如何使用上述迭代器创建一个新的迭代器,使其在每个步骤中随机选择列表中存在的(尚未完成的)迭代器之一,并输出该迭代器的下一个元素?它应该继续输出元素,直到所有迭代器都完成。
例如,如果新的迭代器是 it_combined,则在尝试对其进行迭代时,可以获得以下输出。
>>> for it in it_combined:
...     print(it, end=" ")
...
2 7 3 -1 4 -2 -3 -4 9

1
你能够创建迭代器吗?你看过 itertools 标准库模块文档中的示例吗? - Karl Knechtel
@KarlKnechtel 我已经从这个页面了解了迭代器,但我还没有阅读itertools库模块的文档。我想现在去看看。 - Arun
1
我之所以问是因为现在给出的答案对于那些知道相关技术的人来说很简单。有时候人们确实知道这些东西,只需要被推动一下去尝试。如果你从这些答案中学到了新东西,那就更好了。 - Karl Knechtel
2个回答

5
您可以使用 random.choice 来随机选择列表中的一个迭代器。然后,您需要确保在使用完该迭代器后从列表中删除它。
您可以使用生成器来实现迭代器的合并或抽样:
import random

random.seed(42)


def combine_iterators(iterators):
    while iterators:
        it = random.choice(iterators)
        try:
            yield next(it)
        except StopIteration:
            iterators.remove(it)


merged_iterator = combine_iterators(
    [iter([2, 3, 4]), iter([7, 9]), iter([-1, -2, -3, -4])]
)
for x in merged_iterator:
    print(x, end=" ")

输出:

-1 2 3 -2 7 4 9 -3 -4

2
不幸的是,“简单”方法并不等同。它将无法保留来自同一迭代器的元素的相对顺序。 - Karl Knechtel
啊,当然!你是对的。 - tlgs
@tlgs已添加了一个变体,如果您不喜欢它,请随意回滚。因为它基本上与您的代码相同,我认为这不值得再写一个“答案”。 - Sam Mason

0

这符合您的需求吗?

选择一个随机迭代器并打印其中一个值。一旦该迭代器抛出异常,将其从列表中删除。继续执行,直到所有迭代器都被删除。

import random
iterators = [ iter([2, 3, 4]), iter([7, 9]), iter([-1, -2, -3, -4]) ]

while len(iterators) > 0:
    which = random.randint(0, len(iterators)-1)
    it = iterators[which]
    try:
        print(next(it))
    except Exception:
        del iterators[which]

1
欢迎回到 Stack Overflow。作为复习,请阅读 [答案],并尝试解释您在代码中采取的方法来解决问题。这不是一个编写代码的服务;目标是回答问题,而不是满足 OP 的代码要求。 - Karl Knechtel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接