-3

I need to order lists inside of a list by the numbers in decreasing order. If the number is the same, I have to order it in alphabetical order (increasing).

For example if I have the following list:

mylist=[['a', 5], ['l', 2], ['u', 1], ['t', 1], ['q', 1], ['o', 1], ['e', 1]]

The output has to be like this:

[['a', 5], ['l', 2], ['e', 1], ['o', 1], ['q', 1], ['t', 1], ['u', 1]]

I have searched for this, but I can only found how to order a list. The problem here is that I have to order it by the alphabet just when the number is the same. So the order is first by the numbers (I´ve reached that already), and then I have to order it but the alphabet when the numbers are the same.

pault
  • 41,343
  • 15
  • 107
  • 149
James Paul
  • 13
  • 1
  • 3
  • 2
    Have you searched for how to sort lists? – roganjosh May 10 '18 at 19:46
  • 2
    why does `['y', 0]` come after `['z', 0]`? I do not understand how you want this list to be sorted. – pault May 10 '18 at 19:47
  • 2
    Are you asking how to sort only *part* of the list (those with the second element = 1), leaving the rest unchanged? – pault May 10 '18 at 19:52
  • I think converting it to a dictionary format would be a lot easier to implement and think. Does dictionary approach make sense for this use case? – mad_ May 10 '18 at 19:54
  • I have searched for this, but I can only found how to order a list, but the problem here is that I have to order it by the alphabet just when the number is the same. So the Order is first by the numbers (I´ve reached that already), and then I have to order it but the alphabet when the numbers are the same. – James Paul May 10 '18 at 19:54
  • Yes pault that´s exactly what I need to do – James Paul May 10 '18 at 20:02
  • Does this answer your question? [Python sort list of lists / ascending and then decending](https://stackoverflow.com/questions/6666748/python-sort-list-of-lists-ascending-and-then-decending) – Georgy Aug 09 '20 at 14:24

3 Answers3

3

If I understand correctly you want to sort by the second element (number) descending and by the first element (letter) ascending alphabetically.

This should get what you're looking for:

mylist = list=[['a', 5], ['l', 2], ['u', 1], ['t', 1], ['q', 1], ['o', 1], ['e', 1]]
sorted_list = sorted(mylist, key = lambda x:(-x[1], x[0]))
print(sorted_list)
#[['a', 5], ['l', 2], ['e', 1], ['o', 1], ['q', 1], ['t', 1], ['u', 1]]

We use the key argument to sorted to define how to sort the list. In this case, we pass in a lambda function lambda x: (-x[1], x[0]) as the key function. The "trick" here is that we pass in the negative of x[1] (negative of the number) so that it sorts by the number descending. The second element of the tuple x[0] is the character, which will serve to break ties for list elements with the same number value.

pault
  • 41,343
  • 15
  • 107
  • 149
  • @JamesPaul a great explanation is [here](https://stackoverflow.com/a/8966627/5858851) – pault May 10 '18 at 20:07
  • How would I order with the same conditions but with the reverse order of the alphabet? – James Paul May 10 '18 at 20:23
  • There are two ways that I can think of. 1) If you want to sort descending by both number and letter: pass in `reverse=True` to `sorted()` and remove the negative sign: `sorted(mylist, key = lambda x:(x[1], x[0]), reverse=True)`. 2) Another way is to convert the letter to an ordered numerical representation using `ord` and negate it: `sorted(mylist, key = lambda x:(-x[1], -ord(x[0])))` – pault May 10 '18 at 20:29
0

You can use the key keyword-only argument to change how list.sort evaluates each element of the list. In this case you want it to evaluate the second element of each sublist, or sublist[1].

# don't use `list` as a variable name, it shadows the builtin
lst.sort(key=lambda sublst: sublst[1])

or using operator.itemgetter:

from operator import itemgetter

lst.sort(key=itemgetter(1))
Adam Smith
  • 52,157
  • 12
  • 73
  • 112
  • The question also asks that the result be alphabetized, but the given expected output does not do this so I'm ignoring that part of the requirement – Adam Smith May 10 '18 at 19:49
0

If you want to get more sophisticated you could define a class that defines the '<' operator in the way you want. Then you can either pass a list of instances of your new class to sorted. Or you use the class constructor to generate keys.

For this simple example this seems to be overkill though.

class Foo(list):
    def __lt__(self, other):
        return self[1] > other[1] or (self[1] == other[1] and self[0] < other[0])

sorted(l, key=Foo)
Hinni
  • 166
  • 5