Chris Angelico wrote: > On Tue, Jun 11, 2013 at 6:34 AM, Roy Smith <r...@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() An alternative implementation, based on itertools.tee: import itertools def partition(items, predicate=bool): a, b = itertools.tee((predicate(item), item) for item in items) return ((item for pred, item in a if not pred), (item for pred, item in b if pred)) if __name__ == "__main__": false, true = partition(range(10), lambda item: item % 2) print(list(false)) print(list(true)) def echo_odd(item): print("checking", item) return item % 2 false, true = partition(range(10), echo_odd) print("FALSE", [next(false) for _ in range(3)]) print("TRUE", next(true)) print("FALSE", list(false)) print("TRUE", list(true)) -- http://mail.python.org/mailman/listinfo/python-list