To sort a Python dictionary by its values, use sorted(d.items(), key=lambda item: item[1]). This sorts the key-value pairs by the value and returns a list of tuples. The detail people miss: you do not get a sorted dictionary back - you get a list. If you want an ordered dict, wrap the result: dict(sorted(...)), which works because dictionaries preserve insertion order since Python 3.7. Add reverse=True for descending, and you have covered nearly every real sorting need.
Table of contents
- The core one-liner
- You get a list, not a dict
- Descending, and sorting by key
- operator.itemgetter, the faster lambda
- Breaking ties with a secondary sort
- How this fits the rest of the stack
- FAQ
The core one-liner
scores = {"alice": 88, "bob": 72, "carol": 95}
sorted(scores.items(), key=lambda item: item[1])
# [('bob', 72), ('alice', 88), ('carol', 95)]
Break it down. scores.items() gives the key-value pairs as tuples. sorted(...) sorts them. key=lambda item: item[1] tells sorted to compare by the second element of each tuple - the value - rather than the default, which would sort by the key.
item[1] is the value; item[0] would be the key. That index is the whole trick: change [1] to [0] and you sort by key instead. The lambda is just a tiny function that extracts what to sort on, and sorted handles the rest. This one line is the answer to the question, and everything else is refinement.
You get a list, not a dict
The result of sorted is a list of tuples, not a dictionary:
result = sorted(scores.items(), key=lambda x: x[1])
type(result) # <class 'list'>
This surprises people who expected a sorted dictionary. sorted always returns a list. If a list of pairs is what you want - to iterate in order, to display a ranking - you are done.
If you want a dictionary that preserves the sorted order, wrap it in dict():
ranked = dict(sorted(scores.items(), key=lambda x: x[1]))
# {'bob': 72, 'alice': 88, 'carol': 95}
This works because Python dictionaries have kept insertion order since 3.7 - so building a new dict from the sorted pairs gives you a dict whose iteration order is the sorted order. On any modern Python this is reliable, not a lucky accident. Before 3.7 you would have needed OrderedDict; now a plain dict remembers the order you built it in.
Descending, and sorting by key
For highest-first, add reverse=True:
sorted(scores.items(), key=lambda x: x[1], reverse=True)
# [('carol', 95), ('alice', 88), ('bob', 72)]
That is the top scorers first ordering - the common case for leaderboards and rankings.
To sort by key instead of value, change the lambda index or drop it entirely:
sorted(scores.items()) # by key (default tuple sort)
sorted(scores.items(), key=lambda x: x[0]) # by key, explicit
Sorting items() with no key sorts by the first tuple element, which is the key - so for by-key sorting you often need no lambda at all. The index in the lambda, [0] versus [1], is the switch between sorting by key and by value. Knowing that one detail lets you sort a dict any way you need without looking it up again.
operator.itemgetter, the faster lambda
For the same result with a small speed and readability gain, operator.itemgetter replaces the lambda:
from operator import itemgetter
sorted(scores.items(), key=itemgetter(1)) # by value
sorted(scores.items(), key=itemgetter(0)) # by key
itemgetter(1) does exactly what lambda x: x[1] does, but it is implemented in C, so it is marginally faster and, to many eyes, clearer - it says get item 1 without the lambda ceremony.
For large dictionaries sorted frequently, itemgetter is worth using. For a one-off sort of a small dict, the lambda is perfectly fine and needs no import. Both are correct; itemgetter is the tidier choice when you are already sorting by a fixed position and want the code to read cleanly. It also generalizes: itemgetter(1, 0) sorts by value then key for tie-breaking, in one call.
Breaking ties with a secondary sort
When several values are equal, you often want a consistent secondary order - say, alphabetical by key among equal scores. Return a tuple from the key function:
data = {"z": 5, "a": 5, "m": 3}
sorted(data.items(), key=lambda x: (x[1], x[0]))
# [('m', 3), ('a', 5), ('z', 5)] - by value, then key alphabetically
The key (x[1], x[0]) sorts by value first and uses the key as a tiebreaker, because tuples compare element by element. Among the two items with value 5, a comes before z.
For a descending primary sort with an ascending tiebreak - highest score first, but alphabetical among ties - negate the numeric part:
sorted(data.items(), key=lambda x: (-x[1], x[0]))
Negating the value flips just that field to descending while the key stays ascending. This tuple-key trick is the general answer to multi-level sorting, and it is the same idea whether you are sorting a dict, a list of records, or anything else - build a tuple of the fields in priority order.
How this fits the rest of the stack
Sorting data correctly, with stable tie-breaking, is the quiet foundation under every ranking, leaderboard, and report an app produces. When that logic runs as an endpoint serving ordered results to a UI, getting the sort key and the tie-break right is what makes the output look intentional rather than arbitrary. The RunxBuild hosting calculator lays out the service, database, storage, and bandwidth as separate line items, and the RunxBuild dashboard is where the team watches deploys, logs, and restarts as they happen.
Useful related references:
- Python Get Current Directory: os.getcwd Is Not Where Your Script Lives
- Python or: Short-Circuits, Truthiness, and the Default-Value Trap
- Python str vs repr: Get This Wrong and Your Logs Are Useless
- Python services on RunxBuild
FAQ
How do I sort a dictionary by value in Python?
Use sorted(d.items(), key=lambda item: item[1]), which sorts the key-value pairs by the value and returns a list of tuples. Add reverse=True for descending order. Wrap it in dict(...) if you want a dictionary that keeps the sorted order.
Does sorting a dictionary return a dictionary?
No, sorted returns a list of tuples. To get a dictionary in sorted order, wrap the result in dict() - dict(sorted(d.items(), key=lambda x: x[1])). This works because dictionaries preserve insertion order since Python 3.7.
How do I sort a dictionary by value in descending order?
Add reverse=True: sorted(d.items(), key=lambda x: x[1], reverse=True). This puts the highest values first, which is the common case for leaderboards and rankings. Wrap in dict() if you need an ordered dictionary rather than a list.
What is the difference between sorting by key and by value?
The index in the key function decides it: lambda x: x[1] sorts by value, lambda x: x[0] sorts by key. Sorting d.items() with no key sorts by key by default, since tuples compare on their first element first.
How do I break ties when sorting a dictionary?
Return a tuple from the key function, listing fields in priority order - key=lambda x: (x[1], x[0]) sorts by value then by key. Tuples compare element by element, so equal values fall back to the key. Negate a field, like -x[1], to make just that field descending.