multirember&co

Peter Otten __peter__ at web.de
Tue Apr 17 02:21:16 EDT 2007


bearophileHUGS at lycos.com wrote:

> Once in while I too have something to ask. This is a little problem
> that comes from a Scheme Book (I have left this thread because this
> post contains too much Python code for a Scheme newsgroup):

> For fun I have tried to make it lazy, if may be useful if seq is a
> very long iterable. So I've used tee:
> 
> from itertools import ifilter, tee
> 
> def multiremberandco4(el, iseq, fun):
>     iseq1, iseq2 = tee(iseq)
>     iterable1 = ifilter(lambda x: x == el, iseq1)
>     iterable2 = ifilter(lambda x: x != el, iseq2)
>     return fun(iterable1, iterable2)
> 
> def leniter(seq):
>     count = 0
>     for el in seq:
>         count += 1
>     return count
> 
> idata = iter(data)
> print multiremberandco4('a', idata, lambda l1,l2: (leniter(l1),
> leniter(l2)))
> 
> 
> But from the docs: >in general, if one iterator is going to use most
> or all of the data before the other iterator, it is faster to use
> list() instead of tee().<
> 
> So I have tried to create two iterables for the fun function scanning
> seq once only, but I haven't succed so far (to do it I have tried to
> use two coroutines with the enhanced generators, sending el to one or
> to the other according to the value of x == el, this time I don't show
> my failed versions), do you have suggestions?

I think the showstopper here is fun() which could either combine or
operate indepently on both iterables, e. g.:

def fun(a, b): return [a*b for a, b in zip(a, b)]
def fun(a, b): return sum(a), sum(b)

If you changed multirembrandtco() to accept two functions that are
guaranteed to be independent and to consume all items from their iterable
argument, you could run them in two threads and provide the iterable items
via a Queue that would block fun1() until pending items for fun2() are
processed. 

You'd rather cut your ear off? No, that would be multivangoghco()...

Peter



More information about the Python-list mailing list