multirember&co

Anton Vredegoor anton.vredegoor at gmail.com
Fri Apr 20 12:41:31 CEST 2007


attn.steven.kuo at gmail.com wrote:

> This one gets the order wrong. With
> 
> def test():
>     L = 1, 2, 3, 'a', 4, 'a', 5, 'a', 6, 'a'
>     it1, it2 = xsplitter(L, lambda x: x == 'a')
>     print it1.next()
>     print it2.next()
>     print it1.next()
>     print it2.next()
>     print it1.next()
>     print it2.next()
>     print it1.next()
>     print it2.next()
> 
> 5 will appear before 4.

Thanks. This one will give 4 first and it uses a normal iterator.

from collections import deque

def xsplitter(seq, pred):
     Q = deque(),deque()
     it = iter(seq)
     def gen(p):
         for x in it:
             if pred(x) == p:
                 Q[p].append(x)
                 while Q[p]:  yield Q[p].popleft()
             else:
                 Q[~p].append(x)
                 for x in gen(p):  yield x
         while Q[p]:  yield Q[p].popleft()
     return gen(1),gen(0)

def test():
#    L = 1, 2, 3, 'a', 'a'
#    L = 'a', 1, 2, 'a'
#    L = 1, 'a', 3, 'a', 4, 5, 6, 'a'
     L = 1, 2, 3, 'a', 4, 'a', 5, 'a', 6, 'a'
     it1, it2 = xsplitter(L, lambda x: x == 'a')
     print it1.next()
     print it2.next()
     print it1.next()
     print it2.next()
     print it1.next()
     print it2.next()
     print it1.next()
     print it2.next()
     print it2.next()
     print it2.next()

if __name__=='__main__':
     test()

Because the function can be stopped and resumed anytime, it is possible 
that at the new point of execution the queue has changed.

For example if in these lines from the code above:

             if pred(x) == p:
                 Q[p].append(x)
                 while Q[p]:  yield Q[p].popleft()

I would make the change:

             if pred(x) == p:
                 while Q[p]:  yield Q[p].popleft()
                 yield x

Then the output will be out of order ...

I wonder if this function is OK now.

A.



More information about the Python-list mailing list