Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to sort a list of dictionaries by a list that might contain duplicate values?

Context:
In Python 3.9 sorting a list of most objects by a second list is easy, even if duplicates are present:

>>> sorted(zip([5, 5, 3, 2, 1], ['z', 'y', 'x', 'w', 'x']))
[(1, 'x'), (2, 'w'), (3, 'x'), (5, 'y'), (5, 'z')]

If this list to be sorted contains dictionaries, sorting generally goes fine:

>>> sorted(zip([3, 2, 1], [{'z':1}, {'y':2}, {'x':3}])) 
[(1, {'x': 3}), (2, {'y': 2}), (3, {'z': 1})]

Issue:
However, when the list to be sorted by contains duplicates, the following error occurs:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>>>sorted(zip([5, 5, 3, 2, 1], [{'z':1}, {'y':2}, {'x':3}, {'w': 4}, {'u': 5}])) 
*** TypeError: '<' not supported between instances of 'dict' and 'dict'

The issue sees pretty crazy to me: How do the values of the list to be sorted even affect the list to be sorted by?

Alternative solution:
One, not so elegant solution would be:

>>> sort_list = [5, 5, 3, 2, 1]    
>>> dicts_list = [{'z':1}, {'y':2}, {'x':3}, {'w': 4}, {'u': 5}]
>>> [dicts_list[i] for _, i in sorted(zip(sort_list, range(len(sort_list))))]
 [{'u': 5}, {'w': 4}, {'x': 3}, {'z': 1}, {'y': 2}]

Related Questions on StackOverflow:
Many similar questions have been raised on StackOverflow, related to

This specific case, especially including duplicates has not been discussed yet.

>Solution :

The reason for this is the way tuple comparison works. Generally, if t1 and t2 are tuples, t1 < t2 if t1[0] < t2[0], however if t1[0] == t2[0], then it will compare t1[1] < t2[1] and so on. This means you can compare tuples even if they contain items that can’t be compared to each other, as long as the comparison can differentiate items that come before it.

The standard way to solve this is to provide a key function that ignores the dictionary:

sorted(zip([5, 5, 3, 2, 1], [{'z':1}, {'y':2}, {'x':3}, {'w': 4}, {'u': 5}]), key=lambda item: item[0])
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading