Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #47603 > unrolled thread
| Started by | roy@panix.com (Roy Smith) |
|---|---|
| First post | 2013-06-10 16:34 -0400 |
| Last post | 2013-06-11 22:22 +0200 |
| Articles | 20 on this page of 38 — 17 participants |
Back to article view | Back to comp.lang.python
Split a list into two parts based on a filter? roy@panix.com (Roy Smith) - 2013-06-10 16:34 -0400
Re: Split a list into two parts based on a filter? Chris Angelico <rosuav@gmail.com> - 2013-06-11 08:50 +1000
Re: Split a list into two parts based on a filter? Roel Schroeven <roel@roelschroeven.net> - 2013-06-11 00:50 +0200
Re: Split a list into two parts based on a filter? Roy Smith <roy@panix.com> - 2013-06-11 00:11 -0400
Re: Split a list into two parts based on a filter? Serhiy Storchaka <storchaka@gmail.com> - 2013-06-11 18:27 +0300
Re: Split a list into two parts based on a filter? Roy Smith <roy@panix.com> - 2013-06-11 20:33 -0400
Re: Split a list into two parts based on a filter? Phil Connell <pconnell@gmail.com> - 2013-06-12 07:32 +0100
Re: Split a list into two parts based on a filter? Roy Smith <roy@panix.com> - 2013-06-12 07:39 -0400
Re: Split a list into two parts based on a filter? Fábio Santos <fabiosantosart@gmail.com> - 2013-06-12 12:51 +0100
Re: Split a list into two parts based on a filter? Jussi Piitulainen <jpiitula@ling.helsinki.fi> - 2013-06-12 15:06 +0300
Re: Split a list into two parts based on a filter? Terry Reedy <tjreedy@udel.edu> - 2013-06-12 14:07 -0400
Re: Split a list into two parts based on a filter? Serhiy Storchaka <storchaka@gmail.com> - 2013-06-12 19:28 +0300
Re: Split a list into two parts based on a filter? Fábio Santos <fabiosantosart@gmail.com> - 2013-06-12 17:57 +0100
Re: Split a list into two parts based on a filter? Terry Reedy <tjreedy@udel.edu> - 2013-06-12 14:47 -0400
Re: Split a list into two parts based on a filter? Oscar Benjamin <oscar.j.benjamin@gmail.com> - 2013-06-13 10:43 +0100
Re: Split a list into two parts based on a filter? Chris Rebert <clp2@rebertia.com> - 2013-06-10 16:03 -0700
Re: Split a list into two parts based on a filter? Tim Chase <python.list@tim.thechases.com> - 2013-06-10 18:10 -0500
Re: Split a list into two parts based on a filter? Fábio Santos <fabiosantosart@gmail.com> - 2013-06-11 00:08 +0100
Re: Split a list into two parts based on a filter? alex23 <wuwei23@gmail.com> - 2013-06-11 17:44 -0700
Re: Split a list into two parts based on a filter? Chris Angelico <rosuav@gmail.com> - 2013-06-11 09:12 +1000
Re: Split a list into two parts based on a filter? Peter Otten <__peter__@web.de> - 2013-06-11 02:11 +0200
Re: Split a list into two parts based on a filter? Peter Otten <__peter__@web.de> - 2013-06-11 08:43 +0200
Re: Split a list into two parts based on a filter? Jonas Geiregat <jonas@geiregat.org> - 2013-06-11 08:47 +0200
Re: Split a list into two parts based on a filter? Fábio Santos <fabiosantosart@gmail.com> - 2013-06-11 14:48 +0100
Re: Split a list into two parts based on a filter? rusi <rustompmody@gmail.com> - 2013-06-11 09:37 -0700
Re: Split a list into two parts based on a filter? Fábio Santos <fabiosantosart@gmail.com> - 2013-06-11 18:05 +0100
Re: Split a list into two parts based on a filter? rusi <rustompmody@gmail.com> - 2013-06-11 10:23 -0700
Re: Split a list into two parts based on a filter? Chris Angelico <rosuav@gmail.com> - 2013-06-12 03:37 +1000
Re: Split a list into two parts based on a filter? rusi <rustompmody@gmail.com> - 2013-06-11 11:13 -0700
Re: Split a list into two parts based on a filter? Fábio Santos <fabiosantosart@gmail.com> - 2013-06-11 19:05 +0100
Re: Split a list into two parts based on a filter? Joshua Landau <joshua.landau.ws@gmail.com> - 2013-06-11 15:22 +0100
Re: Split a list into two parts based on a filter? Serhiy Storchaka <storchaka@gmail.com> - 2013-06-11 18:28 +0300
Re: Split a list into two parts based on a filter? Chris Angelico <rosuav@gmail.com> - 2013-06-12 03:28 +1000
Re: Split a list into two parts based on a filter? Roy Smith <roy@panix.com> - 2013-06-11 20:12 -0400
Re: Split a list into two parts based on a filter? Peter Otten <__peter__@web.de> - 2013-06-11 20:13 +0200
Re: Split a list into two parts based on a filter? Peter Otten <__peter__@web.de> - 2013-06-11 20:18 +0200
Re: Split a list into two parts based on a filter? Chris Angelico <rosuav@gmail.com> - 2013-06-12 04:27 +1000
Re: Split a list into two parts based on a filter? Roel Schroeven <roel@roelschroeven.net> - 2013-06-11 22:22 +0200
Page 1 of 2 [1] 2 Next page →
| From | roy@panix.com (Roy Smith) |
|---|---|
| Date | 2013-06-10 16:34 -0400 |
| Subject | Split a list into two parts based on a filter? |
| Message-ID | <kp5d9e$2hf$1@panix2.panix.com> |
I have a list, songs, which I want to divide into two groups.
Essentially, I want:
new_songs = [s for s in songs if s.is_new()]
old_songs = [s for s in songs if not s.is_new()]
but I don't want to make two passes over the list. I could do:
new_songs = []
old_songs = []
for s in songs:
if s.is_new():
new_songs.append(s)
else:
old_songs.append(s)
Which works, but is klunky compared to the two-liner above. This
seems like a common enough thing that I was expecting to find
something in itertools which did this. I'm thinking something along
the lines of:
matches, non_matches = isplit(lambda s: s.is_new, songs)
Does such a thing exist?
[toc] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2013-06-11 08:50 +1000 |
| Message-ID | <mailman.2991.1370904631.3114.python-list@python.org> |
| In reply to | #47603 |
On Tue, Jun 11, 2013 at 6:34 AM, Roy Smith <roy@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
[toc] | [prev] | [next] | [standalone]
| From | Roel Schroeven <roel@roelschroeven.net> |
|---|---|
| Date | 2013-06-11 00:50 +0200 |
| Message-ID | <mailman.2992.1370904643.3114.python-list@python.org> |
| In reply to | #47603 |
Roy Smith schreef:
> I have a list, songs, which I want to divide into two groups.
> Essentially, I want:
>
> new_songs = [s for s in songs if s.is_new()]
> old_songs = [s for s in songs if not s.is_new()]
>
> but I don't want to make two passes over the list. I could do:
>
> new_songs = []
> old_songs = []
> for s in songs:
> if s.is_new():
> new_songs.append(s)
> else:
> old_songs.append(s)
>
> Which works, but is klunky compared to the two-liner above. This
> seems like a common enough thing that I was expecting to find
> something in itertools which did this. I'm thinking something along
> the lines of:
>
> matches, non_matches = isplit(lambda s: s.is_new, songs)
>
> Does such a thing exist?
You could do something like:
new_songs, old_songs = [], []
[(new_songs if s.is_new() else old_songs).append(s) for s in songs]
But I'm not sure that that's any better than the long version.
--
"People almost invariably arrive at their beliefs not on the basis of
proof but on the basis of what they find attractive."
-- Pascal Blaise
roel@roelschroeven.net
[toc] | [prev] | [next] | [standalone]
| From | Roy Smith <roy@panix.com> |
|---|---|
| Date | 2013-06-11 00:11 -0400 |
| Message-ID | <roy-12F8FA.00111311062013@news.panix.com> |
| In reply to | #47612 |
In article <mailman.2992.1370904643.3114.python-list@python.org>, Roel Schroeven <roel@roelschroeven.net> wrote: > new_songs, old_songs = [], [] > [(new_songs if s.is_new() else old_songs).append(s) for s in songs] Thanks kind of neat, thanks. I'm trying to figure out what list gets created and discarded. I think it's [None] * len(songs).
[toc] | [prev] | [next] | [standalone]
| From | Serhiy Storchaka <storchaka@gmail.com> |
|---|---|
| Date | 2013-06-11 18:27 +0300 |
| Message-ID | <mailman.3023.1370964449.3114.python-list@python.org> |
| In reply to | #47637 |
11.06.13 07:11, Roy Smith написав(ла): > In article <mailman.2992.1370904643.3114.python-list@python.org>, > Roel Schroeven <roel@roelschroeven.net> wrote: > >> new_songs, old_songs = [], [] >> [(new_songs if s.is_new() else old_songs).append(s) for s in songs] > > Thanks kind of neat, thanks. > > I'm trying to figure out what list gets created and discarded. I think > it's [None] * len(songs). It is the same as your klunky code, but consumes more memory.
[toc] | [prev] | [next] | [standalone]
| From | Roy Smith <roy@panix.com> |
|---|---|
| Date | 2013-06-11 20:33 -0400 |
| Message-ID | <roy-10ED1B.20334411062013@news.panix.com> |
| In reply to | #47665 |
In article <mailman.3023.1370964449.3114.python-list@python.org>,
Serhiy Storchaka <storchaka@gmail.com> wrote:
> 11.06.13 07:11, Roy Smith написав(ла):
> > In article <mailman.2992.1370904643.3114.python-list@python.org>,
> > Roel Schroeven <roel@roelschroeven.net> wrote:
> >
> >> new_songs, old_songs = [], []
> >> [(new_songs if s.is_new() else old_songs).append(s) for s in songs]
> >
> > Thanks kind of neat, thanks.
> >
> > I'm trying to figure out what list gets created and discarded. I think
> > it's [None] * len(songs).
>
> It is the same as your klunky code, but consumes more memory.
Well, continuing down this somewhat bizarre path:
new_songs, old_songs = [], []
itertools.takewhile(
lambda x: True,
(new_songs if s.is_new() else old_songs).append(s) for s in songs)
)
I'm not sure I got the syntax exactly right, but the idea is anything
that will iterate over a generator expression. That at least gets rid
of the memory requirement to hold the throw-away list :-)
[toc] | [prev] | [next] | [standalone]
| From | Phil Connell <pconnell@gmail.com> |
|---|---|
| Date | 2013-06-12 07:32 +0100 |
| Message-ID | <mailman.3050.1371018754.3114.python-list@python.org> |
| In reply to | #47716 |
[Multipart message — attachments visible in raw view] — view raw
On 12 Jun 2013 01:36, "Roy Smith" <roy@panix.com> wrote: > > In article <mailman.3023.1370964449.3114.python-list@python.org>, > Serhiy Storchaka <storchaka@gmail.com> wrote: > > > 11.06.13 07:11, Roy Smith написав(ла): > > > In article <mailman.2992.1370904643.3114.python-list@python.org>, > > > Roel Schroeven <roel@roelschroeven.net> wrote: > > > > > >> new_songs, old_songs = [], [] > > >> [(new_songs if s.is_new() else old_songs).append(s) for s in songs] > > > > > > Thanks kind of neat, thanks. > > > > > > I'm trying to figure out what list gets created and discarded. I think > > > it's [None] * len(songs). > > > > It is the same as your klunky code, but consumes more memory. > > Well, continuing down this somewhat bizarre path: > > new_songs, old_songs = [], [] > itertools.takewhile( > lambda x: True, > (new_songs if s.is_new() else old_songs).append(s) for s in songs) > ) > > I'm not sure I got the syntax exactly right, but the idea is anything > that will iterate over a generator expression. That at least gets rid > of the memory requirement to hold the throw-away list :-) You could equivalently pass the generator to deque() with maxlen=0 - this consumes the iterator with constant memory usage. We are of course firmly in the twilight zone at this point (although this can be a useful technique in general). Cheers, Phil > > -- > http://mail.python.org/mailman/listinfo/python-list >
[toc] | [prev] | [next] | [standalone]
| From | Roy Smith <roy@panix.com> |
|---|---|
| Date | 2013-06-12 07:39 -0400 |
| Message-ID | <roy-84E0BB.07395112062013@news.panix.com> |
| In reply to | #47743 |
In article <mailman.3050.1371018754.3114.python-list@python.org>,
Phil Connell <pconnell@gmail.com> wrote:
> > Well, continuing down this somewhat bizarre path:
> >
> > new_songs, old_songs = [], []
> > itertools.takewhile(
> > lambda x: True,
> > (new_songs if s.is_new() else old_songs).append(s) for s in songs)
> > )
> >
> > I'm not sure I got the syntax exactly right, but the idea is anything
> > that will iterate over a generator expression. That at least gets rid
> > of the memory requirement to hold the throw-away list :-)
>
> You could equivalently pass the generator to deque() with maxlen=0 - this
> consumes the iterator with constant memory usage.
>
> We are of course firmly in the twilight zone at this point (although this
> can be a useful technique in general).
We've been in the twilight zone for a while. That's when the fun
starts. But, somewhat more seriously, I wonder what, exactly, it is
that freaks people out about:
>>>> [(new_songs if s.is_new() else old_songs).append(s) for s in songs]
Clearly, it's not the fact that it build and immediately discards a
list, because that concern is addressed with the generator hack, and I
think everybody (myself included) agrees that's just horrible.
Or, is it the use of the conditional to create the target for append()?
Would people be as horrified if I wrote:
for s in songs:
(new_songs if s.is_new() else old_songs).append(s)
or even:
for s in songs:
the_right_list = new_songs if s.is_new() else old_songs
the_right_list.append(s)
[toc] | [prev] | [next] | [standalone]
| From | Fábio Santos <fabiosantosart@gmail.com> |
|---|---|
| Date | 2013-06-12 12:51 +0100 |
| Message-ID | <mailman.3064.1371037923.3114.python-list@python.org> |
| In reply to | #47785 |
[Multipart message — attachments visible in raw view] — view raw
On 12 Jun 2013 12:43, "Roy Smith" <roy@panix.com> wrote: > > In article <mailman.3050.1371018754.3114.python-list@python.org>, > Phil Connell <pconnell@gmail.com> wrote: > > > > Well, continuing down this somewhat bizarre path: > > > > > > new_songs, old_songs = [], [] > > > itertools.takewhile( > > > lambda x: True, > > > (new_songs if s.is_new() else old_songs).append(s) for s in songs) > > > ) > > > > > > I'm not sure I got the syntax exactly right, but the idea is anything > > > that will iterate over a generator expression. That at least gets rid > > > of the memory requirement to hold the throw-away list :-) > > > > You could equivalently pass the generator to deque() with maxlen=0 - this > > consumes the iterator with constant memory usage. > > > > We are of course firmly in the twilight zone at this point (although this > > can be a useful technique in general). > > We've been in the twilight zone for a while. That's when the fun > starts. But, somewhat more seriously, I wonder what, exactly, it is > that freaks people out about: > > >>>> [(new_songs if s.is_new() else old_songs).append(s) for s in songs] > > Clearly, it's not the fact that it build and immediately discards a > list, because that concern is addressed with the generator hack, and I > think everybody (myself included) agrees that's just horrible. I think someone has already said that the problem is that you're creating the list comprehension just for the side effects. > Or, is it the use of the conditional to create the target for append()? I particularly liked that part.
[toc] | [prev] | [next] | [standalone]
| From | Jussi Piitulainen <jpiitula@ling.helsinki.fi> |
|---|---|
| Date | 2013-06-12 15:06 +0300 |
| Message-ID | <qotobbb354j.fsf@ruuvi.it.helsinki.fi> |
| In reply to | #47785 |
Roy Smith writes: > We've been in the twilight zone for a while. That's when the fun > starts. But, somewhat more seriously, I wonder what, exactly, it is > that freaks people out about: > > >>>> [(new_songs if s.is_new() else old_songs).append(s) for s in songs] > > Clearly, it's not the fact that it build and immediately discards a > list, because that concern is addressed with the generator hack, and > I think everybody (myself included) agrees that's just horrible. I expect e(s) in [e(s) for s in songs] to be an expression that is evaluated for its value and not for an effect. The comprehension should stand for a list of those values. The one above violates this expectation. > Or, is it the use of the conditional to create the target for append()? > Would people be as horrified if I wrote: > > for s in songs: > (new_songs if s.is_new() else old_songs).append(s) > > or even: > > for s in songs: > the_right_list = new_songs if s.is_new() else old_songs > the_right_list.append(s) These are fine.
[toc] | [prev] | [next] | [standalone]
| From | Terry Reedy <tjreedy@udel.edu> |
|---|---|
| Date | 2013-06-12 14:07 -0400 |
| Message-ID | <mailman.3117.1371060481.3114.python-list@python.org> |
| In reply to | #47785 |
On 6/12/2013 7:39 AM, Roy Smith wrote: > starts. But, somewhat more seriously, I wonder what, exactly, it is > that freaks people out about: > >>>>> [(new_songs if s.is_new() else old_songs).append(s) for s in songs] > > Clearly, it's not the fact that it build and immediately discards a > list, because that concern is addressed with the generator hack, and I > think everybody (myself included) agrees that's just horrible. It is an example of comprehension abuse. Comprehensions express and condense a stylized pattern of creating collections from another collection or collections, possibly filtered. They were not mean to replace for statements and turn Python into an fp languages. Indeed, they do replace and expand upon the fp map function. Python for loops are not evil. > Or, is it the use of the conditional to create the target for append()? > Would people be as horrified if I wrote: > > for s in songs: > (new_songs if s.is_new() else old_songs).append(s) No. That succinctly expresses and implements the idea 'append each song to one of two lists. > or even: > > for s in songs: > the_right_list = new_songs if s.is_new() else old_songs > the_right_list.append(s) > -- Terry Jan Reedy
[toc] | [prev] | [next] | [standalone]
| From | Serhiy Storchaka <storchaka@gmail.com> |
|---|---|
| Date | 2013-06-12 19:28 +0300 |
| Message-ID | <mailman.3112.1371054538.3114.python-list@python.org> |
| In reply to | #47716 |
12.06.13 09:32, Phil Connell написав(ла): > On 12 Jun 2013 01:36, "Roy Smith" <roy@panix.com <mailto:roy@panix.com>> > wrote: > > Well, continuing down this somewhat bizarre path: > > > > new_songs, old_songs = [], [] > > itertools.takewhile( > > lambda x: True, > > (new_songs if s.is_new() else old_songs).append(s) for s in songs) > > ) > > > > I'm not sure I got the syntax exactly right, but the idea is anything > > that will iterate over a generator expression. That at least gets rid > > of the memory requirement to hold the throw-away list :-) > > You could equivalently pass the generator to deque() with maxlen=0 - > this consumes the iterator with constant memory usage. any((new_songs if s.is_new() else old_songs).append(s) for s in songs)
[toc] | [prev] | [next] | [standalone]
| From | Fábio Santos <fabiosantosart@gmail.com> |
|---|---|
| Date | 2013-06-12 17:57 +0100 |
| Message-ID | <mailman.3114.1371056243.3114.python-list@python.org> |
| In reply to | #47716 |
Why is there no builtin to consume a generator? I find that odd. On Wed, Jun 12, 2013 at 5:28 PM, Serhiy Storchaka <storchaka@gmail.com> wrote: > 12.06.13 09:32, Phil Connell написав(ла): >> >> On 12 Jun 2013 01:36, "Roy Smith" <roy@panix.com <mailto:roy@panix.com>> >> >> wrote: >> > Well, continuing down this somewhat bizarre path: >> > >> > new_songs, old_songs = [], [] >> > itertools.takewhile( >> > lambda x: True, >> > (new_songs if s.is_new() else old_songs).append(s) for s in songs) >> > ) >> > >> > I'm not sure I got the syntax exactly right, but the idea is anything >> > that will iterate over a generator expression. That at least gets rid >> > of the memory requirement to hold the throw-away list :-) >> >> You could equivalently pass the generator to deque() with maxlen=0 - >> this consumes the iterator with constant memory usage. > > > any((new_songs if s.is_new() else old_songs).append(s) for s in songs) > > > -- > http://mail.python.org/mailman/listinfo/python-list -- Fábio Santos
[toc] | [prev] | [next] | [standalone]
| From | Terry Reedy <tjreedy@udel.edu> |
|---|---|
| Date | 2013-06-12 14:47 -0400 |
| Message-ID | <mailman.3118.1371062857.3114.python-list@python.org> |
| In reply to | #47716 |
On 6/12/2013 12:57 PM, Fábio Santos wrote:
> Why is there no builtin to consume a generator? I find that odd.
There are several builtins than consume generators -- and do something
useful with the yielded objects. What you mean is "Why is there no
builtin to uselessly consume a generator?" The question almost answers
itself. A generator generates objects to be used.
> On Wed, Jun 12, 2013 at 5:28 PM, Serhiy Storchaka <storchaka@gmail.com> wrote:
>> 12.06.13 09:32, Phil Connell написав(ла):
>>> You could equivalently pass the generator to deque() with maxlen=0 -
>>> this consumes the iterator with constant memory usage.
>> any((new_songs if s.is_new() else old_songs).append(s) for s in songs)
The problem here is that the generator generates and yields an unwanted
sequence of None (references) from the append operations. The proper
loop statement
for s in songs:
(new_songs if s.is_new() else old_songs).append(s)
simply ignores the None return of the appends. Since it does not yield
None over and over, no extra code is needed to ignore what should be
ignored in the first place.
--
Terry Jan Reedy
[toc] | [prev] | [next] | [standalone]
| From | Oscar Benjamin <oscar.j.benjamin@gmail.com> |
|---|---|
| Date | 2013-06-13 10:43 +0100 |
| Message-ID | <mailman.3178.1371116623.3114.python-list@python.org> |
| In reply to | #47716 |
On 12 June 2013 19:47, Terry Reedy <tjreedy@udel.edu> wrote:
> The proper loop statement
>
> for s in songs:
> (new_songs if s.is_new() else old_songs).append(s)
I think I would just end up rewriting this as
for s in songs:
if s.is_new():
new_songs.append(s)
else:
old_songs.append(s)
but then we're back where we started. I don't think any of the
solutions posted in this thread have been better than this. If you
want to make this a nice one-liner then just put this code in a
function.
Oscar
[toc] | [prev] | [next] | [standalone]
| From | Chris Rebert <clp2@rebertia.com> |
|---|---|
| Date | 2013-06-10 16:03 -0700 |
| Message-ID | <mailman.2994.1370905425.3114.python-list@python.org> |
| In reply to | #47603 |
On Mon, Jun 10, 2013 at 1:34 PM, Roy Smith <roy@panix.com> wrote: > I have a list, songs, which I want to divide into two groups. > Essentially, I want: > > new_songs = [s for s in songs if s.is_new()] > old_songs = [s for s in songs if not s.is_new()] > > but I don't want to make two passes over the list. I could do: > > new_songs = [] > old_songs = [] > for s in songs: > if s.is_new(): > new_songs.append(s) > else: > old_songs.append(s) > > Which works, but is klunky compared to the two-liner above. This > seems like a common enough thing that I was expecting to find > something in itertools which did this. I'm thinking something along > the lines of: > > matches, non_matches = isplit(lambda s: s.is_new, songs) > > Does such a thing exist? itertools.groupby() is kinda similar, but unfortunately doesn't fit the bill due to its sorting requirement. There is regrettably no itertools.partition(). And given how dead-set Raymond seems to be against adding things to the itertools module, there will likely never be. Maybe more-itertools (https://pypi.python.org/pypi/more-itertools ) would accept a patch? Cheers, Chris
[toc] | [prev] | [next] | [standalone]
| From | Tim Chase <python.list@tim.thechases.com> |
|---|---|
| Date | 2013-06-10 18:10 -0500 |
| Message-ID | <mailman.2995.1370905719.3114.python-list@python.org> |
| In reply to | #47603 |
On 2013-06-11 08:50, Chris Angelico wrote: > 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=[],[] This is really nice. I think the only major modification I'd make is to use a collections.deque() instead of lists here: trues, falses = collections.deque(), collections.deque() as I seem to recall that list.pop(0) has some performance issues if it gets long, while the deque is optimized for fast (O(1)?) push/pop on either end. -tkc
[toc] | [prev] | [next] | [standalone]
| From | Fábio Santos <fabiosantosart@gmail.com> |
|---|---|
| Date | 2013-06-11 00:08 +0100 |
| Message-ID | <mailman.2996.1370905734.3114.python-list@python.org> |
| In reply to | #47603 |
[Multipart message — attachments visible in raw view] — view raw
On 10 Jun 2013 23:54, "Roel Schroeven" <roel@roelschroeven.net> wrote: > > You could do something like: > > new_songs, old_songs = [], [] > [(new_songs if s.is_new() else old_songs).append(s) for s in songs] > > But I'm not sure that that's any better than the long version. This is so beautiful!
[toc] | [prev] | [next] | [standalone]
| From | alex23 <wuwei23@gmail.com> |
|---|---|
| Date | 2013-06-11 17:44 -0700 |
| Message-ID | <51638894-039f-4449-a322-c3e16184efa3@ow4g2000pbc.googlegroups.com> |
| In reply to | #47616 |
On Jun 11, 9:08 am, Fábio Santos <fabiosantos...@gmail.com> wrote: > On 10 Jun 2013 23:54, "Roel Schroeven" <r...@roelschroeven.net> wrote: > > new_songs, old_songs = [], [] > > [(new_songs if s.is_new() else old_songs).append(s) for s in songs] > > This is so beautiful! No, it's actually pretty terrible. It creates a list in order to populate _two other lists_ and then throws away the one made by the comprehension. There's nothing ugly about multiline for-loops.
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2013-06-11 09:12 +1000 |
| Message-ID | <mailman.2997.1370905986.3114.python-list@python.org> |
| In reply to | #47603 |
On Tue, Jun 11, 2013 at 9:10 AM, Tim Chase <python.list@tim.thechases.com> wrote: > On 2013-06-11 08:50, Chris Angelico wrote: >> 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=[],[] > > This is really nice. I think the only major modification I'd make is > to use a collections.deque() instead of lists here: > > trues, falses = collections.deque(), collections.deque() > > as I seem to recall that list.pop(0) has some performance issues if > it gets long, while the deque is optimized for fast (O(1)?) push/pop > on either end. Sure. If it's that good I might submit it to more-itertools... heh. ChrisA
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | comp.lang.python
csiph-web