Fate of itertools.dropwhile() and itertools.takewhile()
Paul Hankin
paul.hankin at gmail.com
Sun Dec 30 21:50:11 EST 2007
On Dec 31, 1:25 am, Raymond Hettinger <pyt... at rcn.com> wrote:
> FWIW, here is an generator version written without the state flag:
>
> def iter_block(lines, start_marker, end_marker):
> lines = iter(lines)
> for line in lines:
> if line.startswith(start_marker):
> yield line
> break
> for line in lines:
> if line.startswith(end_marker):
> return
> yield line
Here's a (stateful) version that generates all blocks...
import itertools
def iter_blocks(lines, start_marker, end_marker):
inblock = [False]
def line_in_block(line):
inblock[0] = inblock[0] and not line.startswith(end_marker)
inblock[0] = inblock[0] or line.startswith(start_marker)
return inblock[0]
return (block for is_in_block, block in
itertools.groupby(lines, line_in_block) if is_in_block)
If you just want the first block (as the original code did), you can
just take it...
for line in iter_blocks(lines, start_marker, end_marker).next():
... process lines of first block.
I'm not happy about the way the inblock state has to be a 1-element
list to avoid the non-local problem. Is there a nicer way to code it?
Otherwise, I quite like this code (if I do say so myself) as it neatly
separates out the logic of whether you're inside a block or not from
the code that yields blocks and lines. I'd say it was quite readable
if you're familiar with groupby.
And back on topic... I use itertools regularly (and have a functional
background), but have never needed takewhile or dropwhile. I'd be
happy to see them deprecated.
--
Paul Hankin
More information about the Python-list
mailing list