Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Python's sorted() method not reverse orders of keys with the same value in a dictionary?

I was working through some old Advent of Code problems in preparation for this year's when I came across the following oddity. Let's say we have the following Python dictionary:

d = {'a':5, 'b':4, 'c':4, 'd':2, 'e':3, 'f':1}

If we sort this dictionary by its keys, we get the following:

>>>print(sorted(d, key=d.get))
['f','e','d','c','b','a']

Now, if we try to reverse this order, we get the following:

>>>print(sorted(d, key=d.get, reverse=True))
['a','c','b','d','e','f']

This raised two question to me:

  1. Why does the original sort by keys list c before b despite the fact that when traversing the dictionary, the first time it sees 4 is with the key b?
  2. Why does the reversed order keep this ordering rather than reversing the order of the keys found in the original sort?

I'm sure there are other ways to solve this problem, but now I'm curious as to what the mechanics of the sorted method are that are causing this.

like image 910
mathsman Avatar asked Nov 21 '19 02:11

mathsman


1 Answers

reverse=True doesn't mean sort the input and then reverse it. reverse=True means reverse the comparison results:

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

The sort is still stable, so elements equal in comparison order are kept in the order they appeared in the input.


Now, you might think, hey, 'c' wasn't before 'b' in the input! That means you must be on a Python version where dicts don't preserve insertion order, so the dict's order isn't the order you wrote the items in your source code. The order sorted saw its input was essentially arbitrary. If you want an order-preserving dict, you'll have to use a newer Python or collections.OrderedDict.

like image 72
user2357112 supports Monica Avatar answered Sep 28 '22 14:09

user2357112 supports Monica