Search code examples
pythonpython-itertools

Exhaust a list of generators in a cyclic fashion


I have a list of generator functions like:

def myGen(x):
    for i in range(x):
        yield i
g5 = myGen(5); g10 = myGen(10); g15 = myGen(15)
cycleList = [g5, g10, g15]

What is the best way to cycle between these generators and remove the ones that are exhausted from the list?

The output should be:

0 0 0 1 1 1 2 2 2 3 3 3 4 4 4 5 5 6 6 7 7 8 8 9 9 10 11 12 13 14

Solution

  • It looks like you want the roundrobin itertools recipe:

    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))
    

    In use:

    >>> from itertools import cycle, islice
    >>> for i in roundrobin(xrange(5), xrange(10), xrange(15)):
        print i,
    
    
    0 0 0 1 1 1 2 2 2 3 3 3 4 4 4 5 5 6 6 7 7 8 8 9 9 10 11 12 13 14