【问题标题】:How to sample from an Iterable of generators in python 3?如何从 python 3 中的生成器迭代中采样?
【发布时间】:2018-09-05 13:51:30
【问题描述】:

给定 listgenerator 值:

from itertools import repeat

ones_gen = repeat(1)

twos_gen = repeat(2)

threes_gen = repeat(3)

gen_list = [ones_gen, twos_gen, threes_gen]

如何创建另一个生成器,从列表中采样以交错来自底层原始生成器的值?

新的生成器应该产生1 2 3 1 2 3 1 2 3...

注意:这是一个可以被cycle([1,2,3]) 复制的简单示例,但只是一个示例。

提前感谢您的考虑和回复。

【问题讨论】:

    标签: python-3.x generator


    【解决方案1】:

    chain.from_iterablezip 一起使用

    >>> cc = chain.from_iterable(zip(*gen_list))
    >>> next(cc)
    1
    >>> next(cc)
    2
    >>> next(cc)
    3
    >>> next(cc)
    1
    >>> next(cc)
    2
    >>> next(cc)
    3
    

    如果生成器不是无限的,并且具有不同的长度,您可能希望使用循环策略。 itertools recipes中有一个例子。

    【讨论】:

    • 考虑到这要求所有输入生成器具有相同的长度(其中长度可以是无限的)。
    【解决方案2】:

    如果你的生成器都是相同的长度(包括无限长),你可以chain togetherzip()生成的值:

    from itertools import chain
    
    chain.from_iterable(zip(*gen_list))
    

    如果长度可能不同并且应该丢弃耗尽的生成器,请使用roundrobin() example from the itertools documentation

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

    后者的演示:

    >>> from itertools import repeat, islice
    >>> ones_gen = repeat(1)
    >>> twos_gen = repeat(2)
    >>> limited_threes_gen = islice(repeat(3), 2)  # just two values
    >>> rrgen = roundrobin(ones_gen, twos_gen, limited_threes_gen)
    >>> next(rrgen)
    1
    >>> next(rrgen)
    2
    >>> next(rrgen)
    3
    >>> next(rrgen)
    1
    >>> next(rrgen)
    2
    >>> next(rrgen)
    3
    >>> next(rrgen)
    1
    >>> next(rrgen)
    2
    >>> next(rrgen)
    1
    

    3s 用完了,但其他两个生成器继续运行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-02-10
      • 1970-01-01
      • 1970-01-01
      • 2014-04-04
      • 1970-01-01
      • 1970-01-01
      • 2018-11-01
      相关资源
      最近更新 更多