Sorting a list python

Viewed 113

I need to sort the below list :

[('Elijah', 51), ('Chloe', 144), ('Elizabeth', 485), ('Matthew', 485), ('Natalie', 207), ('Jayden', 390)]

It should be sorted based on the no. And if there are any two similar no's it is sorted alphabetically according to the name. The final ans should be

[('Elizabeth', 485), ('Matthew', 485), ('Jayden', 390), ('Natalie', 207), ('Chloe', 144), ('Elijah', 51)].

I am not able to understand the method given by the author. He wrote:

scores.sort(key=lambda x: (-x[1],x[0]))
print(scores)

In this scores refer to the above given list. Can anyone explain me what exactly happens.

2 Answers

Breakdown:

list.sort:

scores.sort(...) # sorts the list in-place

This method sorts the list in place, using only < comparisons between items. Exceptions are not suppressed - if any comparison operations fail, the entire sort operation will fail (and the list will likely be left in a partially modified state).

key parameter in sort:

key=... # sort the list by some function applied to each item

key specifies a function of one argument that is used to extract a comparison key from each list element (for example, key=str.lower). The key corresponding to each item in the list is calculated once and then used for the entire sorting process. The default value of None means that list items are sorted directly without calculating a separate key value.

The key function:

lambda x: (-x[1],x[0]) # sort each item by the second and then first member

The negation (-x[1]) is only so that the list is sorted in reversed manner relating to the first item (biggest to smallest).

Depending on what the expected output is, using the reversed parameter may have been more clear:

reverse is a boolean value. If set to True, then the list elements are sorted as if each comparison were reversed.

Itemgetter is a neat tool for sorting like this as it can be used hierarchically. See below...

from operator import itemgetter as ig
data_sorted = sorted(data, key=ig(1,0), reverse=True)

The reverse changes ascending vs. descending.

EDIT:

As was pointed out this will only address sorting one column. The easiest solution would be to sort twice. First by the secondary sorting column (name in this case), and then by the primary sorting column (Number Value).

ds1 = sorted(data, key=ig(0), reverse=True)

ds2 = sorted(ds1, key=ig(1), reverse=True)

Resulting in...

('Elizabeth', 485)
('Matthew', 485)
('Jayden', 390)
('Natalie', 207)
('Chloe', 144)
('Elijah', 51)
Related