Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python sorting dictionaries: Key [Ascending] and then Value [Descending]

Tags:

python

sorting

I have looked for ages and have found no actual answers because I can't see any that start with an ascending key and then by a descending value.

An example to make it clearer:

d = {'banana':3, 'orange':5, 'apple':5}
out: [('apple', 5), ('orange', 5), ('banana', 3)]

After doing some research I arrived at something like:

sorted(d.items(), key=operator.itemgetter(1,0), reverse=True)
out: [('orange', 5), ('apple', 5), ('banana', 3)]

This is because it's reverse-sorting both the value and the key. I need the key to be un-reversed.

I'd really appreciate some help here. Thanks in advance!

like image 672
RulerOfTheWorld Avatar asked Feb 21 '16 17:02

RulerOfTheWorld


People also ask

How do you sort a dictionary in descending order based on value in Python?

reverse with a value of True will arrange the sorted dictionary in descending order. You can see the output is reversed because we passed reverse=True to the sorted() method. If you don't set reverse at all or you set its value to false, the dictionary will be arranged in ascending order. That's the default.


2 Answers

What you are asking is not possible as stated. Not only are dictionaries unordered (which can be overcome with an OrderedDict), but their keys are unique, which means the idea of sorting by key and then by value is nonsensical.

What you want is to either use a list of tuples instead, or to use an OrderedDict in which the values are lists (so that they can have multiple values and be sorted.)

List of tuples:

x = [(1,7), (5,3), (8,3), (1,4), (12,4), (12,7), (12,5)]
x.sort(key=itemgetter(1), reverse=True)
x.sort(key=itemgetter(0))
# result: [(1, 7), (1, 4), (5, 3), (8, 3), (12, 7), (12, 5), (12, 4)]
like image 98
Jason S Avatar answered Oct 22 '22 09:10

Jason S


Like others say, keys are unique in dictionaries, so if you sort d.items() by key, there is no more sorting to do. But what if you want to sort first by descending value and then by ascending key?

out = list(sorted(d.items(), key=(lambda item: (-item[1],item[0]))))

Result: [('apple', 5), ('orange', 5), ('banana', 3)]

Explanation: When sorting tuples, the elements are considered in sequence. In the expression above I have used a new tuple derived from the original tuple item, to flip the order and also flip the sign of the number.

like image 44
Elias Hasle Avatar answered Oct 22 '22 09:10

Elias Hasle