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?
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.
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)}
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]
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?
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.
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)}
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]