Python
Dictionary
Filtering
Keys
Programming Tips

Filter dict to contain only certain keys?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Filtering a dictionary to keep only the keys you care about is one of the most common operations when working with data in Python. You encounter it when processing API responses that return dozens of fields but you only need three, or when sanitizing user input before passing it to a function. Python gives you several clean ways to do this, each with different tradeoffs.

This article covers four approaches: dictionary comprehension, the dict constructor with a generator, operator.itemgetter, and set intersection with direct key access.

Dictionary Comprehension

The most Pythonic and widely used approach is a dictionary comprehension that iterates over the desired keys and picks values from the source dictionary.

python
1original = {'name': 'Alice', 'age': 30, 'email': '[email protected]', 'role': 'admin'}
2allowed_keys = {'name', 'email'}
3
4filtered = {k: v for k, v in original.items() if k in allowed_keys}
5print(filtered)
6# {'name': 'Alice', 'email': '[email protected]'}

This iterates over every key-value pair in the original dictionary and keeps only those whose key is in allowed_keys. Using a set for allowed_keys gives O(1) membership checks, so the overall time complexity is O(n) where n is the size of the original dictionary.

If you want to be safe when the allowed keys might not exist in the original, this pattern handles it gracefully because the if condition simply skips missing keys.

Dict Constructor with a Generator

You can also pass a generator expression to the dict() constructor. This is functionally identical to the comprehension but some developers find it reads more clearly when the filtering logic is simple.

python
1original = {'name': 'Alice', 'age': 30, 'email': '[email protected]', 'role': 'admin'}
2allowed_keys = {'name', 'email'}
3
4filtered = dict((k, original[k]) for k in allowed_keys if k in original)
5print(filtered)
6# {'name': 'Alice', 'email': '[email protected]'}

Notice that this version iterates over allowed_keys rather than over the original dictionary. When allowed_keys is much smaller than the original dictionary, this approach does less work. The if k in original guard prevents KeyError for keys that do not exist in the source.

Using operator.itemgetter

The operator.itemgetter function retrieves multiple values from a dictionary in a single call. This is useful when you know all the desired keys exist and you want both the keys and values extracted together.

python
1from operator import itemgetter
2
3original = {'name': 'Alice', 'age': 30, 'email': '[email protected]', 'role': 'admin'}
4keys_to_keep = ('name', 'email')
5
6values = itemgetter(*keys_to_keep)(original)
7filtered = dict(zip(keys_to_keep, values))
8print(filtered)
9# {'name': 'Alice', 'email': '[email protected]'}

One important detail: if any key in keys_to_keep is missing from the original dictionary, itemgetter raises a KeyError. This makes it a good choice when you want to enforce that all expected keys are present, essentially treating the filtering as a strict projection. Also note that when keys_to_keep contains only one element, itemgetter returns a single value instead of a tuple, so you need to handle that edge case if the number of keys is dynamic.

Set Intersection with Direct Key Access

This pattern uses set intersection to find which of your desired keys actually exist in the dictionary, then builds a new dictionary from those keys.

python
1original = {'name': 'Alice', 'age': 30, 'email': '[email protected]', 'role': 'admin'}
2allowed_keys = {'name', 'email', 'phone'}  # 'phone' does not exist
3
4# dict.keys() supports set operations directly
5present_keys = original.keys() & allowed_keys
6
7filtered = {k: original[k] for k in present_keys}
8print(filtered)
9# {'name': 'Alice', 'email': '[email protected]'}

The & operator works because dict.keys() returns a view object that supports set operations. This approach makes the intent very explicit: first compute the intersection of available and desired keys, then build the result. It is especially readable when you need to reuse present_keys for other logic, such as logging which requested keys were missing.

Choosing the Right Approach

ApproachHandles missing keysIterates overBest when
Dict comprehensionYes (skips them)Original dictGeneral purpose, most common
Dict constructor + generatorYes (with guard)Allowed keysAllowed set is much smaller
operator.itemgetterNo (raises KeyError)Allowed keysYou want strict validation
Set intersectionYes (intersection filters)IntersectionYou need the key overlap explicitly

Common Pitfalls

  • Using a list instead of a set for allowed keys. Membership checks in a list are O(n), while a set gives O(1). For large dictionaries or large key lists, this difference matters.
  • Forgetting to handle missing keys. If you write {k: original[k] for k in allowed_keys} without a guard, any key in allowed_keys that is not in the original dictionary raises a KeyError. Use if k in original or the dict.get method.
  • Mutating the original dictionary instead of creating a new one. Deleting keys from the original with a loop like for k in list(d.keys()): if k not in allowed: del d[k] modifies the source data, which can cause bugs if other code holds a reference to it.
  • Assuming dictionary order does not matter. Since Python 3.7, dictionaries maintain insertion order. If you filter by iterating over allowed_keys, the result follows the order of allowed_keys, not the original dictionary. This can matter for serialization or display.
  • Overcomplicating simple filters. For straightforward cases, a one-line dictionary comprehension is the clearest and most maintainable option. Reaching for itemgetter or multi-step set operations when a comprehension would suffice adds unnecessary complexity.

Summary

  • Dictionary comprehension ({k: v for k, v in d.items() if k in allowed}) is the default choice for filtering dictionaries in Python.
  • When the set of desired keys is much smaller than the dictionary, iterate over the keys instead of the dictionary for better performance.
  • operator.itemgetter is useful when you want strict validation that all requested keys exist.
  • Set intersection (d.keys() & allowed) makes the overlap between available and desired keys explicit and reusable.
  • Always use a set (not a list) for the collection of allowed keys to ensure O(1) membership checks.

Course illustration
Course illustration

All Rights Reserved.