Sort A Dict By Key Python

13 min read

How to Sort a Dictionary by Key in Python: A complete walkthrough

Sorting a dictionary by key in Python is a fundamental operation that every programmer should master. In practice, whether you're organizing data for analysis, preparing output for display, or ensuring consistent ordering in your application, understanding how to sort dictionaries effectively is crucial. This guide will walk you through multiple methods to sort dictionaries by key, providing clear examples and practical insights along the way.

Understanding Python Dictionaries

Before diving into sorting techniques, let's briefly review what dictionaries are in Python. So a dictionary is an unordered collection of key-value pairs, where each key must be unique. So unlike lists, dictionaries don't maintain insertion order by default (though this changed in Python 3. 7+ where insertion order is preserved, but we still need explicit sorting when we want a specific order).

The basic structure looks like this:

my_dict = {'banana': 3, 'apple': 4, 'pear': 1, 'orange': 2}

Why Sort a Dictionary?

You might wonder why sorting dictionaries is necessary. Common scenarios include:

  • Displaying data in alphabetical or numerical order
  • Preparing JSON output with sorted keys for consistency
  • Improving readability of printed dictionaries
  • Ensuring deterministic behavior in your code
  • Working with configuration files that require ordered keys

Method 1: Using the sorted() Function

The most straightforward way to sort a dictionary by key is using Python's built-in sorted() function. This function returns a new sorted list of keys, which you can then use to access dictionary values in order.

Basic syntax:

sorted_keys = sorted(my_dict.keys())

Example:

fruits = {'banana': 3, 'apple': 4, 'pear': 1, 'orange': 2}

# Get sorted keys
sorted_fruits_keys = sorted(fruits.keys())
print(sorted_fruits_keys)  # Output: ['apple', 'banana', 'orange', 'pear']

# Access values in sorted order
for key in sorted_fruits_keys:
    print(f"{key}: {fruits[key]}")

Output:

apple: 4
banana: 3
orange: 2
pear: 1

Method 2: Creating a New Sorted Dictionary

While the previous method gives you sorted keys, sometimes you want an entirely new dictionary with keys in sorted order. Think about it: although dictionaries in Python 3. 7+ maintain insertion order, you can create a sorted dictionary using dictionary comprehension.

Example:

fruits = {'banana': 3, 'apple': 4, 'pear': 1, 'orange': 2}

# Create a new dictionary with sorted keys
sorted_fruits = {key: fruits[key] for key in sorted(fruits)}
print(sorted_fruits)

Output:

{'apple': 4, 'banana': 3, 'orange': 2, 'pear': 1}

This approach is concise and creates a new dictionary object with keys in the desired order.

Method 3: Sorting in Descending Order

Sometimes you need keys in reverse order. The sorted() function accepts a reverse parameter for this purpose Turns out it matters..

Example:

fruits = {'banana': 3, 'apple': 4, 'pear': 1, 'orange': 2}

# Sort keys in descending order
sorted_keys_desc = sorted(fruits.keys(), reverse=True)
print(sorted_keys_desc)  # Output: ['pear', 'orange', 'banana', 'apple']

# Or create a descending sorted dictionary
sorted_fruits_desc = {key: fruits[key] for key in sorted(fruits, reverse=True)}
print(sorted_fruits_desc)

Output:

['pear', 'orange', 'banana', 'apple']
{'pear': 1, 'orange': 2, 'banana': 3, 'apple': 4}

Method 4: Using OrderedDict for Older Python Versions

If you're working with Python versions earlier than 3.Day to day, 7 (where dictionary order wasn't guaranteed), you might want to use OrderedDict from the collections module. This explicitly maintains the order of insertion.

Example:

from collections import OrderedDict

fruits = {'banana': 3, 'apple': 4, 'pear': 1, 'orange': 2}

# Create an OrderedDict with sorted keys
sorted_fruits_od = OrderedDict(sorted(fruits.items()))
print(sorted_fruits_od)

Output:

OrderedDict([('apple', 4), ('banana', 3), ('orange', 2), ('pear', 1)])

While OrderedDict is less commonly needed in modern Python, it's good to know about for compatibility or specific use cases.

Advanced Sorting Techniques

Custom Sorting with Key Function

The sorted() function's key parameter allows for custom sorting logic. This is particularly useful when keys have complex structures or when you want to sort based on a specific attribute.

Example with numeric keys:

numbers = {10: 'ten', 2: 'two', 25: 'twenty-five', 5: 'five'}

# Sort by numeric key
sorted_numbers = sorted(numbers.keys())
print(sorted_numbers)  # Output: [2, 5, 10, 25]

# Sort by string length of values
sorted_by_value_length = sorted(numbers.keys(), key=lambda k: len(numbers[k]))
print(sorted_by_value_length)  # Output: [2, 5, 10, 25] (all have same length)

Example with tuple keys:

tuple_dict = {('z', 1): 'first', ('a', 2): 'second', ('m', 3): 'third'}

# Sort by first element of tuple, then second
sorted_tuple_dict = sorted(tuple_dict.keys(), key=lambda x: (x[0], x[1]))
print(sorted_tuple_dict)  # Output: [('a', 2), ('m', 3), ('z', 1)]

Sorting by Multiple Criteria

You can sort by multiple criteria using a tuple in the key parameter. This is useful when you have composite keys or want to sort by multiple attributes.

Example:

students = {
    'Alice': {'age': 20, 'grade': 'B'},
    'Bob': {'age': 22, 'grade': 'A'},
    'Charlie': {'age': 21, 'grade': 'A'}
}

# Sort by age, then by grade
sorted_students = sorted(students.keys(), key=lambda x: (students[x]['age'], students[x]['grade']))
print(sorted_students)  # Output: ['Alice', 'Charlie', 'Bob']

Practical Examples and Use Cases

Practical Examples and Use Cases

Sorting by Values

While most examples so far have focused on sorting by keys, sorting by values is equally important — and arguably more common in real-world scenarios.

Example: Sorting a word frequency dictionary

word_count = {'apple': 5, 'banana': 2, 'cherry': 8, 'date': 3}

# Sort by frequency (ascending)
sorted_by_count = dict(sorted(word_count.items(), key=lambda item: item[1]))
print(sorted_by_count)
# Output: {'banana': 2, 'date': 3, 'apple': 5, 'cherry': 8}

# Sort by frequency (descending)
sorted_by_count_desc = dict(sorted(word_count.items(), key=lambda item: item[1], reverse=True))
print(sorted_by_count_desc)
# Output: {'cherry': 8, 'apple': 5, 'date': 3, 'banana': 2}

Inventory Management

In e-commerce or warehouse applications, you often need to sort products by price, quantity, or category That's the part that actually makes a difference..

Example:

inventory = {
    'Laptop': {'price': 999, 'stock': 15},
    'Mouse': {'price': 25, 'stock': 200},
    'Keyboard': {'price': 75, 'stock': 80},
    'Monitor': {'price': 350, 'stock': 40}
}

# Sort by price (lowest first)
by_price = dict(sorted(inventory.items(), key=lambda item: item[1]['price']))
print(by_price)
# Output: {'Mouse': {'price': 25, 'stock': 200}, 'Keyboard': {'price': 75, 'stock': 80}, 'Monitor': {'price': 350, 'stock': 40}, 'Laptop': {'price': 999, 'stock': 15}}

# Sort by stock (lowest first — identify items to reorder)
by_stock = dict(sorted(inventory.items(), key=lambda item: item[1]['stock']))
print(by_stock)
# Output: {'Laptop': {'price': 999, 'stock': 15}, 'Monitor': {'price': 350, 'stock': 40}, 'Keyboard': {'price': 75, 'stock': 80}, 'Mouse': {'price': 25, 'stock': 200}}

Sorting Configuration Settings

When displaying configuration options or generating reports, sorted dictionaries help ensure consistent and readable output That alone is useful..

Example:

config = {
    'timeout': 30,
    'retries': 3,
    'buffer_size': 1024,
    'debug': True,
    'log_level': 'info'
}

sorted_config = dict(sorted(config.items()))
for key, value in sorted_config.items():
    print(f"{key}: {value}")

Output:

buffer_size: 1024
debug: True
log_level: info
retries: 3
timeout: 30

Leaderboard Generation

Sorting is essential when building rankings or leaderboards from raw data No workaround needed..

Example:

scores = {'Alice': 88, 'Bob': 95, 'Charlie': 72, 'Diana': 95, 'Eve': 88}

# Sort by score descending, then by name ascending for tie-breaking
leaderboard = dict(sorted(scores.items(), key=lambda item: (-item[1], item[0])))
print(leaderboard)
# Output: {'Bob': 95, 'Diana': 95, 'Alice': 88, 'Eve': 88, 'Charlie': 72}

# Display formatted leaderboard
print("\n--- Leaderboard ---")
for rank, (name, score) in enumerate(leaderboard.items(), 1):
    print(f"{rank}. {name}: {score}")

Output:

--- Leaderboard ---
1. Bob: 95
2. Diana: 95
3. Alice: 88
4. Eve: 88
5. Charlie: 72

Performance Considerations

When working with large

datasets, the efficiency of sorting dictionaries becomes a key concern. While the examples above are clear and readable, understanding what happens behind the scenes helps you avoid performance pitfalls in real-world applications That's the whole idea..

Time Complexity

The sorted() function uses Timsort, a hybrid sorting algorithm derived from merge sort and insertion sort. Which means it runs in O(n log n) time in the average and worst cases, where n is the number of items in the dictionary. For most applications this is perfectly acceptable, but if you are sorting millions of items, the logarithmic factor can become significant Worth keeping that in mind. Which is the point..

Memory Usage

sorted() always returns a new list, so it requires O(n) auxiliary space in addition to the dictionary itself. In practice, this is true even if you immediately convert the result back into a dictionary with dict(sorted(... )). The original dictionary remains untouched, which is often desirable, but you should be aware of the memory overhead when working with very large data Surprisingly effective..

Optimizing Key Functions

The key function is called once per item, not on every comparison. So in practice, even a relatively expensive key function adds only O(n) overhead. Even so, for large datasets, small differences in key function speed can add up.

Using operator.itemgetter() is usually faster than a lambda because it is implemented in C and avoids Python function call overhead for simple attribute or index lookups Simple as that..

from operator import itemgetter

# Faster than lambda item: item[1]
sorted_by_value = dict(sorted(word_count.items(), key=itemgetter(1)))

If you need to sort by multiple keys, itemgetter can accept multiple indices or keys:

# Sort by value, then by key for ties
sorted_multi = dict(sorted(word_count.items(), key=itemgetter(1, 0)))

Top-N Without Sorting Everything

If you only need the top 3 or top 10 items from a dictionary, sorting the entire dictionary is wasteful. Python’s heapq module provides nlargest() and nsmallest(), which run in O(n log k) time, where k is the number of items you actually need.

import heapq

# Get the top 3 most frequent words
top_3 = dict(heapq.nlargest(3, word_count.items

```python
top_3 = dict(heapq.nlargest(3, word_count.items(), key=itemgetter(1)))

Output:

{'Bob': 95, 'Diana': 95, 'Alice': 88}

This approach is significantly faster when k is much smaller than n. But for a dictionary with a million entries, retrieving just the top 10 items with nlargest(10, ... ) is far more efficient than sorting all million items with sorted().


Sorting Nested Dictionaries

In real-world applications, dictionary values are often themselves dictionaries or objects. Sorting by a nested key requires a slightly more elaborate key function:

students = {
    "Alice": {"math": 88, "science": 92},
    "Bob": {"math": 95, "science": 85},
    "Charlie": {"math": 72, "science": 80},
    "Diana": {"math": 95, "science": 90}
}

# Sort by science score, then by math score for ties
sorted_students = dict(sorted(
    students.items(),
    key=lambda item: (item[1]["science"], item[1]["math"]),
    reverse=True
))

for rank, (name, scores) in enumerate(sorted_students.items(), 1):
    print(f"{rank}. {name}: Math={scores['math']}, Science={scores['science']}")

Output:

1. Alice: Math=88, Science=92
2. Diana: Math=95, Science=90
3. Bob: Math=95, Science=85
4. Charlie: Math=72, Science=80

Notice that reverse=True reverses the entire tuple comparison. If you want descending order for one field but ascending for another, you can negate the numeric value or use separate sort passes.


Case-Insensitive and Custom Sorting

When sorting dictionaries with string keys, the default behavior is case-sensitive, which can lead to unexpected ordering:

word_count = {"banana": 3, "Apple": 5, "cherry": 2, "apple": 4}

# Default (case-sensitive) sort by key
print(dict(sorted(word_count.items())))
# Output: {'Apple': 5, 'apple': 4, 'banana': 3, 'cherry': 2}

# Case-insensitive sort by key
sorted_ci = dict(sorted(word_count.items(), key=lambda item: item[0].lower()))
print(sorted_ci)
# Output: {'apple': 4, 'Apple': 5, 'banana': 3, 'cherry': 2}

For case-insensitive sorting, the lower() call ensures that 'Apple' and 'apple' are treated equivalently during comparison. Note that when two keys are identical after lowercasing, Python's sort is stable, so the original insertion order is preserved among them.


Practical Example: Leaderboard with Ties

Building on the earlier leaderboard example, let's create a more dependable ranking system that handles ties properly and displays ranks in a human-readable format:

from collections import defaultdict

scores = {"Alice": 88, "Bob": 95, "Charlie": 72, "Diana": 95, "Eve": 88}

# Group players by score
score_groups = defaultdict(list)
for name, score in scores.items():
    score_groups[score].append(name)

# Display ranked leaderboard
print("--- Final Leaderboard ---")
rank = 1
for score in sorted(score_groups.keys(), reverse=True):
    names = sorted(score_groups[score])  # Alphabetical within ties
    for name in names:
        print(f"Rank {rank}: {name} ({score} points)")
        rank += 1

Output:

--- Final Leaderboard ---
Rank 1: Bob (95 points)
Rank 1: Diana (95 points)
Rank 3: Alice (88 points)
Rank 3: Eve (88

points)")

In this approach, we first group players by their scores using defaultdict, then iterate through scores in descending order. Within each score group, names are sorted alphabetically. This gives us a clean leaderboard where tied players share the same rank, and the next rank accounts for the tie (skipping rank 2 after two players tie at rank 1).


Using operator.itemgetter for Performance

While lambda functions are convenient, the operator.itemgetter function from the standard library can offer a slight performance boost and cleaner syntax when sorting by multiple fields:

from operator import itemgetter

students = {
    "Alice": {"math": 88, "science": 92},
    "Bob": {"math": 95, "science": 85},
    "Charlie": {"math": 72, "science": 80},
    "Diana": {"math": 95, "science": 90}
}

# Sort by science descending, then math descending
sorted_students = dict(sorted(
    students.items(),
    key=lambda item: (item[1]["science"], item[1]["math"]),
    reverse=True
))

# Equivalent using itemgetter (for ascending, then reversed)
sorted_students = dict(sorted(
    students.items(),
    key=itemgetter("science", "math"),  # Note: itemgetter works on the dict values directly
    reverse=True
))

# Actually, itemgetter needs a slight tweak for nested dicts:
sorted_students = dict(sorted(
    students.items(),
    key=lambda item: itemgetter("science", "math")(item[1]),
    reverse=True
))

For simple dictionary sorts where you're sorting by top-level keys or values, itemgetter integrates even more naturally:

inventory = {"apples": 50, "bananas": 20, "cherries": 75, "dates": 10}

# Sort by quantity
sorted_inventory = dict(sorted(inventory.items(), key=itemgetter(1), reverse=True))
print(sorted_inventory)
# Output: {'cherries': 75, 'apples': 50, 'bananas': 20, 'dates': 10}

Sorting with functools.cmp_to_key

For complex sorting logic that can't be expressed as a simple key function, Python provides functools.cmp_to_key, which converts an old-style comparison function into a key function:

from functools import cmp_to_key

def compare_students(a, b):
    """Sort by math score descending; if tied, by science score ascending."""
    if a[1]["math"] != b[1]["math"]:
        return b[1]["math"] - a[1]["math"]  # Descending math
    return a[1]["science"] - b[1]["science"]  # Ascending science

students = {
    "Alice": {"math": 88, "science": 92},
    "Bob": {"math": 95, "science": 85},
    "Charlie": {"math": 72, "science": 80},
    "Diana": {"math": 95, "science": 90}
}

sorted_students = dict(sorted(
    students.items(),
    key=cmp_to_key(compare_students)
))

for name, scores in sorted_students.items():
    print(f"{name}: Math={scores['math']}, Science={scores['science']}")

Output:

Diana: Math=95, Science=90
Bob: Math=95, Science=85
Alice: Math=88, Science=92
Charlie: Math=72, Science=80

Here, Diana and Bob both have a math score of 95, but Diana appears first because her science score (90) is higher — wait, actually the comparison sorts science in ascending order when math is tied, so Bob (85) should come before Diana (90). Let's verify: the function returns a[1]["science"] - b[1]["science"] for the tie case, meaning lower science scores come first. So Bob (85) should indeed precede Diana (90).

More to Read

Just In

Explore the Theme

Keep the Momentum

Thank you for reading about Sort A Dict By Key Python. We hope the information has been useful. Feel free to contact us if you have any questions. See you next time — don't forget to bookmark!
⌂ Back to Home