How to write this iterator?
George Sakkis
gsakkis at rutgers.edu
Tue Sep 20 12:25:08 EDT 2005
"Jordan Rastrick" <jrastrick at student.usyd.edu.au> wrote:
> I've written this kind of iterator before, using collections.deque,
> which personally I find a little more elegant than the list based
> approach:
Nice, that's *much* more elegant and simple ! Here's the class-based version with append; note that
interleave is modified to put back the popped iterator before yield, otherwise append doesn't work
properly:
from collections import deque
class Interleave(object):
"""Iterator that cycles over one or more iterables, yielding one item from
each iterable at a time. Once an iterable is exhausted, it is removed from
the cycle. This iterator is exhausted when all participating iterables are
exhausted.
>>> it = Interleave("abc","12345","XY")
>>> list(it)
['a', '1', 'X', 'b', '2', 'Y', 'c', '3', '4', '5']
>>> list(it)
[]
"""
def __init__(self, *iterables):
iters = self.__iters = deque(map(iter, iterables))
def generator():
while iters:
it = iters.popleft()
try:
next = it.next()
except StopIteration:
continue
else:
iters.append(it)
yield next
self.__this_iter = generator()
def append(self,iterable):
"""Adds an iterable to the existing cycle of iterables.
The given iterable is added in front of the current position in the
cycle so that it's called only after all the others.
>>> example = Interleave("abc", "12345")
>>> [example.next() for i in range(3)]
['a', '1', 'b']
>>> example.append("XY")
>>> list(example)
['2', 'c', 'X', '3', 'Y', '4', '5']
"""
self.__iters.append(iter(iterable))
def __iter__(self):
return self
def next(self):
return self.__this_iter.next()
if __name__ == '__main__':
import doctest
doctest.testmod()
More information about the Python-list
mailing list