list comprehensions: sorting?

Alex Martelli aleax at aleax.it
Fri Sep 7 05:29:12 EDT 2001


"Clark C . Evans" <cce at clarkevans.com> wrote in message
news:mailman.999804189.8996.python-list at python.org...
    ...
> |     map(process, sorted_by(2,
> |         [x for x in mylist if x[4]], descend=1))
>
> It works... but it's a bit ugly.  I'd like a
> more "intuitive" syntax... and without having
> to roll my own sort function.  I would think
> that sorting lists as part of a list comprehension
> would be a common activity... I certainly do it
> often enough.

Some kind or other of sorting is very common, but
the specific case your "sortdesc" keyword might
cover if it existed is far too specific and thus
rare -- sorting on a specific "column" of a
list of tuples *before* further processing.

I don't recall offhand the last time I had such
a very specific need -- I sort very frequently,
but it generally has to be descending on this or
ascending on that and guaranteed stable, or
something like that.  And generally I don't
need the further processing to be done after
sorting -- it's fine either way.

So, I'd generally code something like:

result = sort1([
    (-x[2],process(x))
    for x in mylist if x[4]], stable=1)

where:

def sort1(templist, stable=0):
    if stable:
        templist = [((i,srt),payload)
            for i,(srt,payload) in
                zip(xrange(sys.maxint),
                    templist)]
    templist.sort()
    return [x for junk, x in templist]

but that's pretty specific.  If there
just was a NICE way to access the index
in a "for x in y" statement it would
make much more of a difference to the
ease of programming such things, than
any built-in sort-syntax I can think of.

"for i,x in zip(xrange(sys.maxint),y)"
isn't _exactly_ elegant, besides being
a duplication of work, in as much as the
for statement already DOES have an
internal equivalent of that i - it just
refuses to make it available to us:-).


> | def sorted_by(col, alist, descend=0):
> |     temp = [(x[col],x) for x in alist]
> |     temp.sort()
> |     if descend: temp.reverse()
> |     return temp
>
> Thanks... I'm going to use this solution; but
> it'd be cool if list comprehensions were extended
> a bit to allow for sorting...  thank you so much
> for your response Alex.

You're welcome.  And if you can think of some
'orderby' syntax that would actually cover ALL
typical sorting needs with just "a bit" of
extension to the current one, we could surely
write a PEP for it -- but it would HAVE to be
"just a bit" (of extra syntax), and for very
wide generality gains, or the trade-off is a
losing one, I fear.

Currently, built-in sorting is un-handy because
the .sort method of a list sorts in-place, and
returns None "to remind you of that" -- which
is basically never what you want, when you're
trying to sort-on-the-fly, of course:-).  So,
having a function is basically always needed,
even if it's just something like:

def sorted_by(the_list, the_func=None):
    the_list.sort(the_func)
    return the_list


Alex






More information about the Python-list mailing list