Split a list into two parts based on a filter?
Chris Angelico
rosuav at gmail.com
Mon Jun 10 18:50:29 EDT 2013
On Tue, Jun 11, 2013 at 6:34 AM, Roy Smith <roy at panix.com> wrote:
> new_songs = [s for s in songs if s.is_new()]
> old_songs = [s for s in songs if not s.is_new()]
Hmm. Would this serve?
old_songs = songs[:]
new_songs = [songs.remove(s) or s for s in songs if s.is_new()]
Python doesn't, AFAIK, have a "destructive remove and return"
operation, and del is a statement rather than an expression/operator,
but maybe this basic idea could be refined into something more useful.
It guarantees to call is_new only once per song.
The iterator version strikes my fancy. Maybe this isn't of use to you,
but I'm going to try my hand at making one anyway.
>>> def iterpartition(pred,it):
"""Partition an iterable based on a predicate.
Returns two iterables, for those with pred False and those True."""
falses,trues=[],[]
it=iter(it)
def get_false():
while True:
if falses: yield falses.pop(0)
else:
while True:
val=next(it)
if pred(val): trues.append(val)
else: break
yield val
def get_true():
while True:
if trues: yield trues.pop(0)
else:
while True:
val=next(it)
if not pred(val): falses.append(val)
else: break
yield val
return get_false(),get_true()
>>> f,t=iterpartition(lambda x: x%3,range(100000000))
>>> next(t)
1
>>> next(t)
2
>>> next(t)
4
>>> next(t)
5
>>> next(f)
0
>>> next(f)
3
>>> next(f)
6
>>> next(f)
9
>>> next(f)
12
>>> next(t)
7
>>> next(t)
8
Ha. :) Useless but fun.
ChrisA
More information about the Python-list
mailing list