Sorting a dictionary with values as tuple

Question:

I have a dictionary as follows and I want to sort this based on the last element of the tuple in a non-increasing manner. However, if two or more of the last elements are the same, then they should be sorted based on the second element.

    capacity= {
    'one': (57000, 3100, 0.12903225806451613),
 'two': (52911, 2400, 0.125),
 'three': (48200, 2400, 0.125),
 'four': (48200, 2480, 0.125),
 'five': (11464, 1200, 0.20833333333333334),
 'six': (44000, 1172, 0.21331058020477817),
 'seven': (42000, 1172, 0.21331058020477817)}

After sorting by the third element of the tuple I get the following results.

sorted_capacity={k: (v1,v2,v3) for k, (v1,v2,v3) in sorted(capacity.items(), key=lambda x: x[1][2],reverse=True)}



sorted_capacity

{'six': (44000, 1172, 0.21331058020477817),
 'seven': (42000, 1172, 0.21331058020477817),
 'five': (11464, 1200, 0.20833333333333334),
 'one': (57000, 3100, 0.12903225806451613),
 'two': (52911, 2400, 0.125),
 'three': (48200, 2400, 0.125),
 'four': (48200, 2480, 0.125)}

However, as I mentioned before, I need to have 'four': (48200, 2480, 0.125)} before 'two': (52911, 2400, 0.125), because 2480 is higher than 2400. Basically my output should be like this:

sorted_capacity

    {'six': (44000, 1172, 0.21331058020477817),
     'seven': (42000, 1172, 0.21331058020477817),
     'five': (11464, 1200, 0.20833333333333334),
     'one': (57000, 3100, 0.12903225806451613),
     'four': (48200, 2480, 0.125),
     'two': (52911, 2400, 0.125),
     'three': (48200, 2400, 0.125)
     }

Can anyone help me figure out how to achieve this?

Asked By: mars

||

Answers:

Use

key = lambda x: (x[1][-1], x[1][1])

This compares tuples of the last and second elements in each tuple. Since tuples are ordered lexicographically, this produces the ordering you want.

Answered By: Barmar

In the key function, you can reverse the tuples to compare:

>>> dict(sorted(capacity.items(), key=lambda item: item[1][::-1], reverse=True))
{'six': (44000, 1172, 0.21331058020477817),
 'seven': (42000, 1172, 0.21331058020477817),
 'five': (11464, 1200, 0.20833333333333334),
 'one': (57000, 3100, 0.12903225806451613),
 'four': (48200, 2480, 0.125),
 'two': (52911, 2400, 0.125),
 'three': (48200, 2400, 0.125)}
Answered By: Mechanic Pig

Your code with the issue fixed:

from pprint import pprint

capacity = {
    'one': (57000, 3100, 0.12903225806451613),
    'two': (52911, 2400, 0.125),
    'three': (48200, 2400, 0.125),
    'four': (48200, 2480, 0.125),
    'five': (11464, 1200, 0.20833333333333334),
    'six': (44000, 1172, 0.21331058020477817),
    'seven': (42000, 1172, 0.21331058020477817)}

sorted_capacity = {
    k: (v1, v2, v3)
    for k, (v1, v2, v3) in sorted(capacity.items(), key=lambda x: (x[1][2], x[1][1]), reverse=True)
}

pprint(sorted_capacity, sort_dicts=False)  # don't want pprint to sort again

This just adds the middle column to the sorting key. If you want the first column to be used when the second is also identical, you could also just reverse the tuple:

key=lambda x: tuple(reversed(x[1]))

Or:

key=lambda x: x[1][::-1]
Answered By: Grismar
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.