On Apr 16, 5:14 pm, [EMAIL PROTECTED] 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):http://groups.google.com/group/comp.lang.scheme/browse_thread/thread/...
>


(snipped)

>
> 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?


Scan once, two iterables:

class It(object):
    def __init__(self, iseq, fun, fun2):
        self.iseq = iseq
        self.wanted = fun
        self.queue = []
        self.divert = fun2
    def append(self, item):
        self.queue.append(item)
    def __iter__(self):
        while True:
            if self.queue:
                yield self.queue.pop(0)
            else:
                try:
                    item = self.iseq.next()
                    if self.wanted(item):
                        yield item
                    else:
                        self.divert(item)
                except StopIteration:
                    raise

class TwoFromOne(object):
    def __init__(self, iseq, el):
        self.i1 = It(iseq, lambda x: x == el, lambda y:
self.i2.append(y))
        self.i2 = It(iseq, lambda x: x != e1, lambda y:
self.i1.append(y))
    def getiters(self):
        return self.i1, self.i2

def leniter(seq):
    count = 0
    for el in seq:
        count += 1
    return count

data =  [1, 'a', 3, 'a', 4, 5, 6, 'a']
lazy_eye = TwoFromOne(iter(data), 'a')
it1, it2 = lazy_eye.getiters()
print (lambda i1, i2: (leniter(i1), leniter(i2)))(it1, it2)

--
Hope this helps,
Steven



-- 
http://mail.python.org/mailman/listinfo/python-list

Reply via email to