This function takes a sequence and a function and returns two generators. The first generator yields all items in the sequence for which function(item) returns True, and the second generator yields all items for which function(item) returns False.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | def partition(seq, func=bool):
true_vals, false_vals = [], []
def true_gen(_seq):
while 1:
if true_vals:
yield true_vals.pop(0)
else:
for item in _seq:
if func(item):
yield item
break
else:
false_vals.append(item)
else:
break
def false_gen(_seq):
while 1:
if false_vals:
yield false_vals.pop(0)
else:
for item in _seq:
if not func(item):
yield item
break
else:
true_vals.append(item)
else:
break
it = iter(seq)
return true_gen(it), false_gen(it)
|
I created this function to emulate a function in Ruby that someone on #python needed.
Tags: algorithms
You can write it more simply by exploiting itertools.tee. Moreover, I would exploit the fact that False == 0 and True == 1, and extend it for n partitions.
By default, you get the same functionality as before, and you can write stuff like this:
Variant. def partition(seq, func=None): s1, s2 = tee(seq) return ifilter(func, s1), ifilterfalse(func, s2)
The difference between my method and these other methods is that mine only iterates once over the sequence and doesn't require teeing the iterator. All-in-all, it probably uses less memory, though it might be longer.
Here's a general version of partition that doesn't tee the iterator.