multirember&co
bearophileHUGS at lycos.com
bearophileHUGS at lycos.com
Tue Apr 17 18:52:33 EDT 2007
Paddy:
> def multiremberandco1(el, seq, fun):
> l1, l2 = [], []
> c = seq.count(e1)
> l1 = [el] * c
> l2 = [el] * (len(seq) - c)
> return fun(l1, l2)
Thank you Paddy, but unfortunately there is a bug in my first
function, this is more correct:
def multiremberandco1b(el, seq, fun):
l1, l2 = [], []
for x in seq:
if x == el:
l2.append(x)
else:
l1.append(x)
return fun(l1, l2)
So your version may become:
def multiremberandco1c(el, seq, fun):
l2 = [el] * seq.count(el)
l1 = filter(lambda x: x != el, seq)
return fun(l1, l2)
-------------------
I am grateful to everyone that has answered me, but Steven has
invented what I was looking for. It's code quite twisted on itself :-)
I have modified, simplified and (hopefully) improved Steven's code
like this (but it may be a bit slower, because the class It is inside
the function?):
import collections
def xsplitter(iseq, pred):
class It(object):
def __init__(self, fun, parity):
self.divert = fun
self.parity = parity
self.queue = collections.deque()
def append(self, item):
self.queue.append(item)
def __iter__(self):
while True:
if self.queue:
yield self.queue.popleft()
else:
try:
item = iseq.next()
if pred(item) == self.parity:
yield item
else:
self.divert(item)
except StopIteration:
raise
it1 = It(lambda y: it2.append(y), True)
it2 = It(lambda y: it1.append(y), False)
return it1, it2
idata = iter([1, 'a', 3, 'a', 4, 5, 6, 'a'])
it1, it2 = xsplitter(idata, lambda x: x == 'a')
from itertools import izip
for el1, el2 in izip(it1, it2):
print el1, el2
(The izip stops when the first iterable ends, with while-True loop and
more code that they can be printed fully). Now this code is the lazy
splitter I was talking about. I don't know if it can be useful, but I
like it enough. Probably it's useless if one iterable is used whole
before the other one (because a deque becomes filled up more and
more), so I think in most situations a much simpler eager list
splitter is enough. So I don't know if an improved version of it is
fit for the itertools module.
So far I haven't succed using the coroutine Python 2.5 allows using
the generators, and I think still that xsplitter can be done with two
coroutines instead of two It objects. Despite Steven's code I am
unable still to write a working code with coroutines (probably because
I haven't understood how they work yet). This time I take a breath and
I show my wrong code:
import collections
def xsplitter(iseq, pred):
def it(parity):
queue = collections.deque()
while True:
received = (yield)
if received is not None:
queue.append(received)
if queue:
yield queue.popleft()
else:
try:
el = iseq.next()
if pred(el) == parity:
yield el
else:
its[not parity].send(el)
except StopIteration:
raise
its = [it(False), it(True)]
return its[True], its[False]
idata = iter([1, 'a', 3, 'a', 4, 5, 6, 'a'])
it1, it2 = xsplitter(idata, lambda x: x == 'a')
from itertools import izip
for el1, el2 in izip(it1, it2):
print el1, el2
It prints:
None None
None None
a 3
None None
a 4
None None
None None
None None
Can it be fixed? Are you able to fix it for me? (If you want you can
think of it as an exercise to understand Python coroutines :-) ).
Bye and thank you,
bearophile
More information about the Python-list
mailing list