"Jordan Rastrick" <[EMAIL PROTECTED]> 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() -- http://mail.python.org/mailman/listinfo/python-list