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
Post a Comment