python - How not to miss the next element after itertools.takewhile() -


say wish process iterator , want handle chunks.
logic per chunk depends on previously-calculated chunks, groupby() not help.

our friend in case itertools.takewhile():

while true:     chunk = itertools.takewhile(getnewchunklogic(), myiterator)     process(chunk) 

the problem takewhile() needs go past last element meets new chunk logic, 'eating' first element next chunk.

there various solutions that, including wrapping or à la c's ungetc(), etc..
question is: there elegant solution?

takewhile() indeed needs @ next element determine when toggle behaviour.

you use wrapper tracks last seen element, , can 'reset' 1 element:

_sentinel = object()  class onestepbuffered(object):     def __init__(self, it):         self._it = iter(it)         self._last = _sentinel         self._next = _sentinel     def __iter__(self):         return self     def __next__(self):         if self._next not _sentinel:             next_val, self._next = self._next, _sentinel             return next_val         try:             self._last = next(self._it)             return self._last         except stopiteration:             self._last = self._next = _sentinel             raise     next = __next__  # python 2 compatibility     def step_back(self):         if self._last _sentinel:             raise valueerror("can't step")         self._next, self._last = self._last, _sentinel 

wrap iterator in 1 before using takewhile():

myiterator = onestepbuffered(myiterator) while true:     chunk = itertools.takewhile(getnewchunklogic(), myiterator)     process(chunk)     myiterator.step_back() 

demo:

>>> itertools import takewhile >>> test_list = range(10) >>> iterator = onestepbuffered(test_list) >>> list(takewhile(lambda i: < 5, iterator)) [0, 1, 2, 3, 4] >>> iterator.step_back() >>> list(iterator) [5, 6, 7, 8, 9] 

Comments