By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,629 Members | 1,222 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,629 IT Pros & Developers. It's quick & easy.

How to write this iterator?

P: n/a
Given a list of iterators, I'd like to have a new one that would
cyclically walk over the list calling the next() method of the iterators
(removing any iterator which is exhausted). It should also support adding
a new iterator to the list; it should be added in front of the current
position (so that it's called only after all the others). This is what I
was able to write with my zero python skills (self.iters is the list of
iterators, self.i is the index of the iterator that should be used next).
Is there a nicer/more pythonic solution, maybe using generators?
class Liter(object):

def __init__(self, *iters):
self.i=0
self.iters=[iter(x) for x in iters]

def append(self,what):
self.iters.insert(self.i,what)

def __iter__(self):
return self

def next(self):
while True:
try:
result=self.iters[self.i].next()
except StopIteration:
del self.iters[self.i]
except IndexError:
if len(self.iters) is 0:
raise StopIteration
else:
self.i=0
else:
self.i+=1
return result

Sep 19 '05 #1
Share this Question
Share on Google+
3 Replies


P: n/a
Hmm, here's an approach using the .throw() operation from PEP 342.
It's obviously untested, since that feature is not currently part of
Python, probably incorrect, and maybe just insane. I renamed "append"
to "insert_iterator" since "append" usually means put something at the
end, not in the middle.

from itertools import cycle
class InsertIterator(Exception): pass

def itergen(self, *iters):
while iters:
try:
for i,it in (enumerate(it) for it in cycle(iters)):
yield it.next()
except StopIteration:
del iters[i]
except InsertIterator, new_iterator:
# maybe the i here should be i+1?
iters = [new_iterator] + iters[i:] + iters[:i]

Now you can say

ig = itergen(it1,it2,...)
for x in ig:
....

and if you want to insert a new iterator, just say

ig.throw(InsertIterator, new_iterator)
Sep 19 '05 #2

P: n/a
Paul Rubin <http://ph****@NOSPAM.invalid> writes:
Hmm, here's an approach using the .throw() operation from PEP 342.
It's obviously untested, since that feature is not currently part of
Python, probably incorrect, and maybe just insane.


Pardon the unintentional "shift/reduce conflict" above. I mean that
the code sample I posted is probably incorrect and maybe insane, not
that the proposed throw() feature is incorrect or insane.
Sep 19 '05 #3

P: n/a
se****@sophia.dtp.fmph.uniba.sk wrote:
Given a list of iterators, I'd like to have a new one that would
cyclically walk over the list calling the next() method of the iterators
(removing any iterator which is exhausted). It should also support adding
a new iterator to the list; it should be added in front of the current
position (so that it's called only after all the others). This is what I
was able to write with my zero python skills (self.iters is the list of
iterators, self.i is the index of the iterator that should be used next).
Is there a nicer/more pythonic solution, maybe using generators?


A generator version:

def iterconcat (collectionlist):
for collection in collectionlist:
for element in collection:
yield element

Extending collectionlist at runtime will work only with lists and
similar collections. And you'll need to keep a reference to it as well.
And it would be called after all the others, which matches your
description, but not your code.

Daniel
Sep 19 '05 #4

This discussion thread is closed

Replies have been disabled for this discussion.