Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[Tut] How to Filter a Dictionary in Python? (… The Most Pythonic Way)
1
How to Filter a Dictionary in Python? (… The Most Pythonic Way)



Problem: Given a dictionary and a filter condition. How to filter a dictionary by …
  • … key so that only those
    Code:
    (key, value)
    pairs in the dictionary remain where the key satisfies the condition?

  • … value so that only those
    Code:
    (key, value)
    pairs remain where the value satisfies the condition?

[Image: filter-1-1024x576.jpg]

In this tutorial, you’ll learn four methods and how they compare against each other. It’s loosely based on this tutorial but extends it by many additional examples and code explanations.

If you’re too busy to read this tutorial, here’s the spoiler:

Method 4 — Dictionary comprehension
Code:
{k:v for (k,v) in dict.items() if condition}
is the most Pythonic and fastest way to filter a dictionary in Python.


However, by reading this short 8-minute tutorial, you’re going to learn a lot about the nuances of writing Pythonic code. So keep reading!

Method 1: Simple Iteration to Filter Dictionary

You should always start with the simplest method to solve a problem (see Occam’s razor) because premature optimization is the root of all evil!

So let’s have a look at the straightforward loop iteration method to filter a dictionary.

You start with the following dictionary of names:

Code:
names = {1: 'Alice', 2: 'Bob', 3: 'Carl', 4: 'Ann', 5: 'Liz'}
Filter Python Dictionary By Key (Simple Loop)

You want to keep those
Code:
(key, value)
pairs where key meets a certain condition (such as
Code:
key%2 == 1
).

Code:
newDict = dict() # Iterate over all (k,v) pairs in names for key, value in names.items(): # Is condition satisfied? if key%2 == 1: newDict[key] = value

Let’s have a look at the output:

Code:
print(newDict) # {1: 'Alice', 3: 'Carl', 5: 'Liz'}

Only the
Code:
(key, value)
pairs where the
Code:
key
is an odd integer remain in the filtered dictionary
Code:
newDict
.

But what if you want to filter the dictionary by a condition on the values?

Filter Python Dictionary By Value (Simple Loop)

To filter by value, you only need to replace one line in the previous code snippet: instead of writing if
Code:
key%2 == 1: ...
, you use the
Code:
value
to determine whether to add a certain
Code:
(key, value)
pair:
Code:
if len(value)<5: ...
.

Code:
newDict = dict() # Iterate over all (k,v) pairs in names for key, value in names.items(): # Is condition satisfied? if len(value)<5: newDict[key] = value print(newDict) # {2: 'Bob', 3: 'Carl', 4: 'Ann', 5: 'Liz'}

Only the dictionary
Code:
(key, value)
pairs remain in the filtered dictionary
Code:
newDict
where the length of the name string value is less than five characters.

Try It Yourself in Our Interactive Cod Shell (Click “run”):

https://repl.it/@finxter/filterDict1?lite=true

Now, you know the basic method of filtering a dictionary in Python (by key and by value). But can we do better? What if you need to filter many dictionaries by many different filtering conditions? Do we have to rewrite the same code again and again?

The answer is no! Read on to learn about a more generic way to make filtering a dictionary as easy as calling a function passing the dictionary and the filter function.

Method 2: Generic Function to Filter Dictionary

How can you use different filtering functions on different dictionaries without writing the same code again and again? The answer is simple: create your own generic filtering function!

Your goal is to create a function
Code:
filter_dict(dictionary, filter_func)
that takes a
Code:
dictionary
to be filtered and a
Code:
filter_func
to determine for each
Code:
(key, value)
pair whether it should be included in the filtered dictionary.

You start with the following dictionary of names:

Code:
names = {1: 'Alice', 2: 'Bob', 3: 'Carl', 4: 'Ann', 5: 'Liz'}

Let’s create the generic filter function!

Code:
def filter_dict(d, f): ''' Filters dictionary d by function f. ''' newDict = dict() # Iterate over all (k,v) pairs in names for key, value in d.items(): # Is condition satisfied? if f(key, value): newDict[key] = value return newDict

The function takes two arguments: the dictionary
Code:
d
to be filtered and the function
Code:
f
that decides if an element should be included in the new dictionary.

You create an empty dictionary
Code:
newDict
and decide for all elements of the original dictionary d whether they should be included. To accomplish this, you iterate over each original
Code:
(key, value)
pair and pass it to the function
Code:
f: key, value --> Boolean
. The function
Code:
f
returns a Boolean value. If it evaluates to
Code:
True
, the
Code:
(key, value)
pair is added to the new dictionary. Otherwise, it’s skipped. The return value is the newly created dictionary
Code:
newDict
.

Here’s how you can use the filtering function to filter by key:

Filter Python Dictionary By Key Using Generic Function

If you want to accomplish the same thing as above—filtering by key to include only odd keys—you simply use the following one-liner call:

Code:
print(filter_dict(names, lambda k,v: k%2 == 1)) # {1: 'Alice', 3: 'Carl', 5: 'Liz'}

That was easy! The lambda function you pass returns
Code:
k%2 == 1
which is the Boolean filtering value associated to each original element in the dictionary
Code:
names
.

Similarly, if you want to filter by key to include only even key, you’d do the following:

Code:
print(filter_dict(names, lambda k,v: k%2 == 0)) # {2: 'Bob', 4: 'Ann'}

In fact, it’s equally convenient to filter by value using this exact same strategy:

Filter Python Dictionary By Value Using Generic Function

Here’s how you use our function
Code:
filter_dict
to filter by value:

Code:
print(filter_dict(names, lambda k,v: len(v)<5)) # {2: 'Bob', 3: 'Carl', 4: 'Ann', 5: 'Liz'}

In the previous code snippet, you filter the dictionary so that only those
Code:
(key, value)
pairs remain where the
Code:
value
has less than five characters.

Code:
print(filter_dict(names, lambda k,v: v.startswith('A'))) # {1: 'Alice', 4: 'Ann'}

In this code snippet, you filter the dictionary so that only those
Code:
(key, value)
pairs remain where the
Code:
value
starts with character
Code:
'A'
.

Try It Yourself in Our Interactive Cod Shell (Click “run”):

https://repl.it/@finxter/filterDict2?lite=true

But is this the most Pythonic way? Hardly so! Read on to learn about a functional approach to accomplish the same thing with less code!

(More with less in Python is usually a good thing… Check out my book “Python One-Liners” to master the art of compressing complicated code into a single line.)

Method 3: filter() Function on Dictionary

The
Code:
filter(function, iterable)
function takes a function as input that takes one argument (an element of an iterable) and returns a Boolean value whether this element should pass the filter. All elements that pass the filter are returned as a new
Code:
iterable
object (a filter object).

You can use the
Code:
lambda
function statement to create the function right where you pass it as an argument. The syntax of the lambda function is
Code:
lambda x: expression
and it means that you use
Code:
x
as an input argument and you return expression as a result (that can or cannot use
Code:
x
to decide about the return value). For more information, see my detailed blog article about the lambda function.

Filter Python Dictionary By Key Using filter() + Lambda Functions

Here’s how you can filter a dictionary by key using only a single line of code (without defining your custom filter function as in method 2):

Code:
# FILTER BY KEY print(dict(filter(lambda x: x[0]%2 == 1, names.items()))) # {1: 'Alice', 3: 'Carl', 5: 'Liz'}

You may recognize the same filter lambda function
Code:
lambda x: x[0]%2 == 1
that returns
Code:
True
if the key is an odd integer. Note that this lambda function takes only a single input as this is how the
Code:
filter()
function works (it requires that you pass a function object that takes one argument and maps it to a Boolean value).

You operate on the iterable
Code:
names.items()
that gives you all
Code:
(key, value)
pairs (an element of the iterable is a
Code:
(key, value)
tuple).

After filtering, you convert the filter object back to a dictionary using the
Code:
dict(...)
constructor function.

Another example:

Code:
print(dict(filter(lambda x: x[0]%2 == 0, names.items()))) # {2: 'Bob', 4: 'Ann'}

Let’s see how this works for filtering by value:

Filter Python Dictionary By Value Using filter() + Lambda Functions

You can use the same basic idea—
Code:
filter()
+
Code:
lambda
+
Code:
dict()
—to filter a dictionary by value. For example, if you want to filter out all (key, value) pairs where the value has less than five characters, use the following one-liner:

Code:
print(dict(filter(lambda x: len(x[1])<5, names.items()))) # {2: 'Bob', 3: 'Carl', 4: 'Ann', 5: 'Liz'}

And a second example:

Code:
print(dict(filter(lambda x: x[1].startswith('A'), names.items()))) # {1: 'Alice', 4: 'Ann'}

Try It Yourself in Our Interactive Cod Shell (Click “run”):

https://repl.it/@finxter/filterDict3?lite=true

So, far so good. But can we do any better? I mean, a single line of code is a single line of code, right? How can we possible improve on that?

Method 4: Filter By Dictionary Comprehension

The best way to filter a dictionaryin Python is to use the powerful method of dictionary comprehension.

Dictionary comprehension allows you to transform one dictionary into another one—by modifying each
Code:
(key, value)
pair as you like.

Filter Python Dictionary By Key Using Dictionary Comprehension

The general framework for dictionary comprehension is
Code:
{ expression context }
.
  • Code:
    expression
    defines how you would like to change each (key, value) pair.

  • Code:
    context
    defines the (key, value) pairs, you’d like to include in the new dictionary.

Here’s a practical example that filters all (key, value) pairs with odd keys:

Code:
print({k:v for (k,v) in names.items() if k%2 == 1}) # {1: 'Alice', 3: 'Carl', 5: 'Liz'}

And here’s an example that filters all (key, value) pairs with even keys:

Code:
print({k:v for (k,v) in names.items() if k%2 == 0}) # {2: 'Bob', 4: 'Ann'}

Let’s look at dictionary filtering by value! Is it any different?

Filter Python Dictionary By Value Using Dictionary Comprehension

No! It’s exactly the same:

Code:
print({k:v for (k,v) in names.items() if len(v)<5}) # {2: 'Bob', 3: 'Carl', 4: 'Ann', 5: 'Liz'}

This powerful framework is not only fast and easy to understand, it’s also concise and consistent. The filtering criteria is the last part of the expression so that you can quickly grasp how it’s filtered:

Code:
print({k:v for (k,v) in names.items() if v.startswith('A')}) # {1: 'Alice', 4: 'Ann'}

Try It Yourself in Our Interactive Cod Shell (Click “run”):

https://repl.it/@finxter/filterDict4?lite=true

Related tutorials:

All Four Methods for Copy&Paste

Here are all four methods from the tutorial to simplify copy&pasting:

Code:
names = {1: 'Alice', 2: 'Bob', 3: 'Carl', 4: 'Ann', 5: 'Liz'} ''' Method 1: Simple For Loop ''' # FILTER BY KEY newDict = dict() # Iterate over all (k,v) pairs in names for key, value in names.items(): # Is condition satisfied? if key%2 == 1: newDict[key] = value print(newDict) # {1: 'Alice', 3: 'Carl', 5: 'Liz'} # FILTER BY VALUE newDict = dict() # Iterate over all (k,v) pairs in names for key, value in names.items(): # Is condition satisfied? if len(value)<5: newDict[key] = value print(newDict) # {2: 'Bob', 3: 'Carl', 4: 'Ann', 5: 'Liz'} ''' Method 2: Custom Function ''' def filter_dict(d, f): ''' Filters dictionary d by function f. ''' newDict = dict() # Iterate over all (k,v) pairs in names for key, value in d.items(): # Is condition satisfied? if f(key, value): newDict[key] = value return newDict # FILTER BY KEY print(filter_dict(names, lambda k,v: k%2 == 1)) print(filter_dict(names, lambda k,v: k%2 == 0)) # FILTER BY VALUE print(filter_dict(names, lambda k,v: len(v)<5)) print(filter_dict(names, lambda k,v: v.startswith('A'))) ''' Method 3: filter() ''' # FILTER BY KEY print(dict(filter(lambda x: x[0]%2 == 1, names.items()))) print(dict(filter(lambda x: x[0]%2 == 0, names.items()))) # FITER BY VALUE print(dict(filter(lambda x: len(x[1])<5, names.items()))) print(dict(filter(lambda x: x[1].startswith('A'), names.items()))) ''' Method 4: Dict Comprehension ''' # FITER BY KEY print({k:v for (k,v) in names.items() if k%2 == 1}) print({k:v for (k,v) in names.items() if k%2 == 0}) # FITER BY VALUE print({k:v for (k,v) in names.items() if len(v)<5}) print({k:v for (k,v) in names.items() if v.startswith('A')})

But how do all of those methods compare in terms of algorithmic complexity and runtime? Let’s see…

Algorithmic Analysis

Before we benchmark those methods against each other, let’s quickly discuss computational complexity.

All four methods have linear runtime complexity in the number of elements in the original dictionary to be filtered—assuming that the filtering condition itself has constant runtime complexity (it’s independent of the number of elements in the dictionary).

Method |
Complexity

Method 1: Loop |
O(n)

Method 2: Custom |
O(n)

Method 3: filter() |
O(n)

Method 4: Dictionary Comprehension |
O(n)

But this doesn’t mean that all methods are equally efficient. The dictionary comprehension is usually fastest for these types of filtering operations because it doesn’t use an intermediate function
Code:
filter()
. And it’s also easiest to understand. Therefore, you should use dictionary comprehension in your own code to filter a dictionary by key or by value!

Where to Go From Here?

Enough theory, let’s get some practice!

To become successful in coding, you need to get out there and solve real problems for real people. That’s how you can become a six-figure earner easily. And that’s how you polish the skills you really need in practice. After all, what’s the use of learning theory that nobody ever needs?

Practice projects is how you sharpen your saw in coding!

Do you want to become a code master by focusing on practical code projects that actually earn you money and solve problems for people?

Then become a Python freelance developer! It’s the best way of approaching the task of improving your Python skills—even if you are a complete beginner.

Join my free webinar “How to Build Your High-Income Skill Python” and watch how I grew my coding business online and how you can, too—from the comfort of your own home.

Join the free webinar now!
Reply

Users browsing this thread:
1 Guest(s)


Forum Jump: