2007年6月21日星期四

ASPN : Python Cookbook : Generic block iterator

ASPN : Python Cookbook : Generic block iterator: "_undefined = object() def iterblocks(iterable, start, end=_undefined, skip_delim=True): '''Create an iterator over consecutive items (I{blocks}) of the given iterable. @param start: The delimiter denoting the start of a block. It can be: 1. a predicate C{p(item)} that returns true if the item is a delimiter and false otherwise, or 2. a non-callable object C{obj}: equivalent to C{lambda item: item==start} @param end: If not None, the delimiter denoting the end of a block. Items after an end delimiter but before the next start delimiter are skipped. Takes the same values as C{start}. @param skip_delim: True if the delimiter(s) are to be skipped, false otherwise. @type skip_delim: C{bool} ''' def get_predicate(arg): return arg if callable(arg) else ( arg.__eq__ if hasattr(arg,'__eq__') else lambda item: item == arg) def stamped_items(items): count = 0 startsblock = get_predicate(start) if end is _undefined: for item in items: if startsblock(item): count += 1 if skip_delim: continue yield count,item else: endsblock = get_predicate(end) inblock = False for item in items: if inblock: if endsblock(item): inblock = False if skip_delim: continue elif startsblock(item): count += 1 inblock = True if skip_delim: continue else: continue yield count,item get2nd = itemgetter(1) for count, block in groupby(s"


_undefined = object()

def iterblocks(iterable, start, end=_undefined, skip_delim=True):
'''Create an iterator over consecutive items (I{blocks}) of the given iterable.

@param start: The delimiter denoting the start of a block. It can be:
1. a predicate C{p(item)} that returns true if the item is a
delimiter and false otherwise, or
2. a non-callable object C{obj}: equivalent to C{lambda item: item==start}
@param end: If not None, the delimiter denoting the end of a block. Items
after an end delimiter but before the next start delimiter are skipped.
Takes the same values as C{start}.

@param skip_delim: True if the delimiter(s) are to be skipped, false otherwise.
@type skip_delim: C{bool}
'''
def get_predicate(arg):
return arg if callable(arg) else (
arg.__eq__ if hasattr(arg,'__eq__') else
lambda item: item == arg)
def stamped_items(items):
count = 0
startsblock = get_predicate(start)
if end is _undefined:
for item in items:
if startsblock(item):
count += 1
if skip_delim: continue
yield count,item
else:
endsblock = get_predicate(end)
inblock = False
for item in items:
if inblock:
if endsblock(item):
inblock = False
if skip_delim: continue
elif startsblock(item):
count += 1
inblock = True
if skip_delim: continue
else: continue
yield count,item
get2nd = itemgetter(1)
for count, block in groupby(stamped_items(iterable), itemgetter(0)):
yield imap(get2nd, block)

if __name__ == '__main__':
import re
# a slow version of str.split
for chars in iterblocks('Hello World', re.compile(r'\s').match):
print ''.join(chars)
source = """\
> name1....

line_11
line_12
line_13
...
> name2 ...

line_21
line_22
...""".splitlines()
for lines in iterblocks(source, start=re.compile('>').match, end='...'):
print list(lines)

没有评论: