I need to sort this dict with two sequential criteria: “rank” descending, “fruit” ascending (in case of same ranking result).
The dict is structured in this way
'object':['fruit',rank]
For example I’ve:
myDict = {'item2': ['bananas', 3], 'item3': ['cocumbers', 11], 'item1': ['pinapples', 3], 'item4': ['pears', 3]}
My aim is to obtain this:
{'item3': ['cocumbers', 11], 'item2': ['bananas', 3],'item4': ['pears', 3], 'item1': ['pinapples', 3]}
with
sorted(myDict.items(), key=lambda (k, v): v[1], reverse=True)
I obtain only the correct sorting for rank but with no sorting order for the objects with the same ranking:
[('item3', ['cocumbers', 11]), ('item2', ['bananas', 3]), ('item1', ['pinapples', 3]), ('item4', ['pears', 3])]
How solve this in python 2.7?
Thank’s
sorted(myDict.items(), key=lambda (k, v): (-v[1],v[0]))should do the trick. Since
rankis an integer, we can easily make it sort descending by making the key function just return the negative value rather than needing thereverse=Truekeywords tosorted. In the case of a tie, we fall back on the natural ordering of the strings.This works because sequences in python sort lexicographically (
tuplesare a sequence type) — Python compares elements from each sequence in order until one of the elements is non-equal which gives the ordering of your pair of sequences.In the case where you can’t easily replace
reverse=Truewith a key function, you’ll need to sort twice:This relies on the documented fact that a python sort must be stable. In other words, the relative order of elements that are equal is the same before and after sorting.