Sort dictionary in Python by items inside list
Question:
Is it possible to sort this kind of dictionaries:
- First by rank
- If rank is the same then sort by first element in other_ranks list
- If first element in other_ranks is the same – go deeper until last element in list.
If this is a trouble, I can make this dictionary structurized in different way.
{'rank': 6, 'other_ranks': [7, 5]}
{'rank': 1, 'other_ranks': [7, 11, 6, 2]}
{'rank': 0, 'other_ranks': [12]}
{'rank': 1, 'other_ranks': [13, 11, 4, 3]}
{'rank': 1, 'other_ranks': [14, 12, 6, 5]}
{'rank': 4, 'other_ranks': [5, 4, 3, 2]}
{'rank': 0, 'other_ranks': [12]}
Answers:
Assuming a list, you can use operator.itemgetter
in conjunction with the key argument of sorted
:
from operator import itemgetter
lst = [{'rank': 6, 'other_ranks': [7, 5]},
{'rank': 1, 'other_ranks': [7, 11, 6, 2]},
{'rank': 0, 'other_ranks': [12]},
{'rank': 1, 'other_ranks': [13, 11, 4, 3]},
{'rank': 1, 'other_ranks': [14, 12, 6, 5]},
{'rank': 4, 'other_ranks': [5, 4, 3, 2]},
{'rank': 0, 'other_ranks': [12]}]
res = sorted(lst, key=itemgetter("rank", "other_ranks"))
print(res)
Output
[{'other_ranks': [12], 'rank': 0},
{'other_ranks': [12], 'rank': 0},
{'other_ranks': [7, 11, 6, 2], 'rank': 1},
{'other_ranks': [13, 11, 4, 3], 'rank': 1},
{'other_ranks': [14, 12, 6, 5], 'rank': 1},
{'other_ranks': [5, 4, 3, 2], 'rank': 4},
{'other_ranks': [7, 5], 'rank': 6}]
The key here is that list and tuples are compared lexicographically, from the documentation:
Sequences of the same type also support comparisons. In particular,
tuples and lists are compared lexicographically by comparing
corresponding elements.
Therefore just compare them as is.
That’s called lexigraphical comparison. Python’s tuples implement that.
dictionaries = [
{'rank': 6, 'other_ranks': [7, 5]},
{'rank': 1, 'other_ranks': [7, 11, 6, 2]},
{'rank': 0, 'other_ranks': [12]},
{'rank': 1, 'other_ranks': [13, 11, 4, 3]},
{'rank': 1, 'other_ranks': [14, 12, 6, 5]},
{'rank': 4, 'other_ranks': [5, 4, 3, 2]},
{'rank': 0, 'other_ranks': [12]},
]
dictionaries.sort(key=lambda dict_: (dict_['rank'], ) + tuple(dict_['other_ranks']))
Is it possible to sort this kind of dictionaries:
- First by rank
- If rank is the same then sort by first element in other_ranks list
- If first element in other_ranks is the same – go deeper until last element in list.
If this is a trouble, I can make this dictionary structurized in different way.
{'rank': 6, 'other_ranks': [7, 5]}
{'rank': 1, 'other_ranks': [7, 11, 6, 2]}
{'rank': 0, 'other_ranks': [12]}
{'rank': 1, 'other_ranks': [13, 11, 4, 3]}
{'rank': 1, 'other_ranks': [14, 12, 6, 5]}
{'rank': 4, 'other_ranks': [5, 4, 3, 2]}
{'rank': 0, 'other_ranks': [12]}
Assuming a list, you can use operator.itemgetter
in conjunction with the key argument of sorted
:
from operator import itemgetter
lst = [{'rank': 6, 'other_ranks': [7, 5]},
{'rank': 1, 'other_ranks': [7, 11, 6, 2]},
{'rank': 0, 'other_ranks': [12]},
{'rank': 1, 'other_ranks': [13, 11, 4, 3]},
{'rank': 1, 'other_ranks': [14, 12, 6, 5]},
{'rank': 4, 'other_ranks': [5, 4, 3, 2]},
{'rank': 0, 'other_ranks': [12]}]
res = sorted(lst, key=itemgetter("rank", "other_ranks"))
print(res)
Output
[{'other_ranks': [12], 'rank': 0},
{'other_ranks': [12], 'rank': 0},
{'other_ranks': [7, 11, 6, 2], 'rank': 1},
{'other_ranks': [13, 11, 4, 3], 'rank': 1},
{'other_ranks': [14, 12, 6, 5], 'rank': 1},
{'other_ranks': [5, 4, 3, 2], 'rank': 4},
{'other_ranks': [7, 5], 'rank': 6}]
The key here is that list and tuples are compared lexicographically, from the documentation:
Sequences of the same type also support comparisons. In particular,
tuples and lists are compared lexicographically by comparing
corresponding elements.
Therefore just compare them as is.
That’s called lexigraphical comparison. Python’s tuples implement that.
dictionaries = [
{'rank': 6, 'other_ranks': [7, 5]},
{'rank': 1, 'other_ranks': [7, 11, 6, 2]},
{'rank': 0, 'other_ranks': [12]},
{'rank': 1, 'other_ranks': [13, 11, 4, 3]},
{'rank': 1, 'other_ranks': [14, 12, 6, 5]},
{'rank': 4, 'other_ranks': [5, 4, 3, 2]},
{'rank': 0, 'other_ranks': [12]},
]
dictionaries.sort(key=lambda dict_: (dict_['rank'], ) + tuple(dict_['other_ranks']))