Home > Software engineering >  Sort a dictionary by value (decreasing) and then by key (increasing)
Sort a dictionary by value (decreasing) and then by key (increasing)

Time:12-05

I have a dictionary that I wish to sort first by value in descending order and then by key in increasing (alphabetical) order

My input looks like

{('shall', 'prove'): 1, ('shall', 'not'): 1, ('shall', 'go'): 1, ('shall', 'fight'): 7, ('shall', 'defend'): 1, ('shall', 'never'): 1}

and I'd like my output to look like

[(('shall', 'fight'), 7), (('shall', 'defend'), 1), (('shall', 'go'), 1), (('shall', 'never'), 1), (('shall', 'not'), 1) (('shall', 'prove'), 1), ]

I've tried

def sort_dict(dictionary):
    unsorted_list = list(dictionary.items())
    sorted_list = sorted(unsorted_list, key=operator.itemgetter(1), reverse=True)
    return sorted_list

to sort by value decreasing but I'm unsure how to sort by key increasing at the same time. Please let me know if I need to provide any further information. Thanks!

CodePudding user response:

Sorting the values in descending order is the same as sorting the negative of the values in ascending order. The sort can be done in one go by creating a custom tuple with the values you want to sort according to your priority, i.e., value first and then key.

sorted(dictionary.items(), key=lambda x:(-x[1],)   x[0])
[(('shall', 'fight'), 7), (('shall', 'defend'), 1), (('shall', 'go'), 1), (('shall', 'never'), 1), (('shall', 'not'), 1), (('shall', 'prove'), 1)]

CodePudding user response:

You can leverage the fact that Python's sort is stable and perform the sort in two steps. First sort it in on the least significant component value then on the most significant one:

dictionary = {('shall', 'prove'): 1, ('shall', 'not'): 1,
              ('shall', 'go'): 1, ('shall', 'fight'): 7, 
              ('shall', 'defend'): 1, ('shall', 'never'): 1}

byKeyAscending = sorted(dictionary.items()) 
sortedDict = sorted(byKeyAscending,key=lambda kv:kv[1],reverse=True)

[(('shall', 'fight'), 7), (('shall', 'defend'), 1), 
 (('shall', 'go'), 1), (('shall', 'never'), 1), 
 (('shall', 'not'), 1), (('shall', 'prove'), 1)]

For your particular example, given that the values are numeric, you can use negation to reverse the order and perform the sort in a single step:

sortedDict=sorted(dictionary.items(),key=lambda kv:(-kv[1],kv[0]))
  • Related