Welcome, guest | Sign In | My Account | Store | Cart

This recipe provides a decently simple implementation of a roundrobin using itertools and deque.

Python, 20 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
from itertools import cycle
from collections import deque

def roundrobin(*iterables):
    q = deque(iter(it) for it in iterables)
    for itr in cycle(q):
        try:
            yield itr.next()
        except StopIteration:
            if len(q) > 0:
                q.pop()
            else:
                break

# EXAMPLE

for letter in roundrobin('ABC', 'DE', 'FGH'):
    print letter

# prints 'A', 'D', 'F', 'B', 'E', 'G', 'C', 'H'

Provided in the itertools documentation (http://docs.python.org/library/itertools.html) is an alternative roundrobin implementation credited to George Sakkis.

1 comment

Raymond Hettinger 13 years, 7 months ago  # | flag

The way cycle works, it never sees the shorter deque, so the q.pop() step is not actually doing anything useful.

To see the problem (calling StopIteration way too many times), run this:

from itertools import cycle
from collections import deque

def roundrobin(*iterables):
    q = deque(iter(it) for it in iterables)
    for itr in cycle(q):
        try:
            yield itr.next()
        except StopIteration:
            print 'XXXXXXX'
            if len(q) > 0:
                q.pop()
            else:
                break
for letter in roundrobin('ABC', 'DE', 'FGHIJKLMNOP'):
    print letter