Kelson Zawack writes: > The example I have in mind is list like [2,2,2,2,2,2,1,3,3,3,3] > where you want to loop until you see not a 2 and then you want to > loop until you see not a 3. In this situation you cannot use a for > loop as follows: ... > because it will eat the 1 and not allow the second loop to find it. > takeWhile and dropWhile have the same problem. It is possible to ...
The following may or may not be of interest to you, or to someone else. If not, please ignore. Probably I misuse some of the technical terms. Instead of trying to consume an initial part of an iterable, one can make a new generator that consumes the underlying iterator in the desired way. This works nicely if no other code consumes the same underlying data. My implementation of "after" is below, after the examples, and after that is an alternative implementation. Python 3.1.1 (r311:74480, Feb 8 2010, 14:06:51) [GCC 4.4.3] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> from echoed import * >>> list(after(after([3,1,4,1,5], is2), is3)) [1, 4, 1, 5] >>> list(after(after([2,2,3,1,4,1,5], is2), is3)) [1, 4, 1, 5] >>> list(after(after([2,2,1,4,1,5], is2), is3)) [1, 4, 1, 5] >>> list(after(after([2,2], is2), is3)) [] >>> list(after(after([3,3], is2), is3)) [] >>> list(after(after([], is2), is3)) [] >>> list(after(after([1,4,1,5], is2), is3)) [1, 4, 1, 5] The implementation of "after" uses two simple auxiliaries, "echoed" and "evens", which double every item and drop every other item, respectively. In a sense, "after" returns the echoes of the desired items: when the first item of interest is encountered in the echoed stream, its echo remains there. def echoed(items): for item in items: yield item yield item def evens(items): for item in items: yield item next(items) def after(items, is_kind): echoed_items = echoed(items) try: while is_kind(next(echoed_items)): next(echoed_items) except StopIteration: pass return evens(echoed_items) def is2(x): return x == 2 def is3(x): return x == 3 Alternatively, and perhaps better, one can push the first item of interest back into a new generator. The auxiliary "later" below does that; "past" is the alternative implementation of the desired functionality, used like "after" above. def later(first, rest): yield first for item in rest: yield item def past(items, is_kind): items = iter(items) try: item = next(items) while is_kind(item): item = next(items) except StopIteration: return items return later(item, items) The names of my functions may not be the best. Many more disclaimers apply. -- http://mail.python.org/mailman/listinfo/python-list