Awesome! Thanks for the thorough explanation.
On Sat, Oct 15, 2016 at 11:01 PM, Tim Peters <tim.pet...@gmail.com> wrote:
> [Alireza Rafiei <alireza.rafie...@gmail.com>]
> > I have a list called count_list which contains tuples like below:
> > > [('bridge', 2), ('fair', 1), ('lady', 1), ('is', 2), ('down', 4),
> > > ('london', 2), ('falling', 4), ('my', 1)]
> > I want to sort it based on the second parameter in descending order and
> > tuples with the same second parameter must be sorted based on their first
> > parameter, in alphabetically ascending order. So the ideal output is:
> > > [('down', 4), ('falling', 4), ('bridge', 2), ('is', 2), ('london', 2),
> > > ('fair', 1), ('lady', 1), ('my', 1)]
> I'd like to suggest doing something simple instead, such that
> data = [('bridge', 2), ('fair', 1), ('lady', 1),
> ('is', 2), ('down', 4), ('london', 2),
> ('falling', 4), ('my', 1)]
> from operator import itemgetter
> multisort(data, [# primary key is 2nd element, reversed
> (itemgetter(1), True),
> # secondary key is 1st element, natural
> (itemgetter(0), False)])
> import pprint
> prints the output you want.
> It's actually very easy to do this, but the cost is that it requires
> doing a full sort for _each_ field you want to sort on. Because
> Python's sort is stable, it's sufficient to merely sort on the
> least-significant key first, and then sort again on each key in turn
> through the most-significant. There's another subtlety that makes
> this work:
> > ...
> > The main problem is that reverse argument takes only a boolean and
> > to the whole list after sorting in finished.
> Luckily, that's not how `reverse` actually works. It _first_reverses
> the list, then sorts, and then reverses the list again. The result is
> that items that compare equal _retain_ their original order, where
> just reversing the sorted list would invert their order. That's why,
> in your example above, after first sorting on the string component in
> natural order we get (in part)
> [[('down', 4), ('falling', 4), ...]
> and then reverse-sorting on the integer portion _leaves_ those tuples
> in the same order. That's essential for this decomposition of the
> problem to work.
> With that background, here's the implementation:
> def multisort(xs, specs):
> for key, reverse in reversed(specs):
> xs.sort(key=key, reverse=reverse)
> That's all it takes! And it accepts any number of items in `specs`.
> Before you worry that it's "too slow", time it on real test data.
> `.sort()` is pretty zippy, and this simple approach allows using
> simple key functions. More importantly, it's much easier on your
> brain ;-)
Python-ideas mailing list
Code of Conduct: http://python.org/psf/codeofconduct/