If you want to return the full nested dictionary if it contains a, a list comprehension is probably the cleanest way. Your initial list comprehension would work:

[foo[n] for n in foo if foo[n]['a'] == 10]

You can also avoid the lookup on n with:

[d for d in foo.values() if d['a'] == 10]

List comprehensions are generally considered more Pythonic than map or filter related approaches for simpler problems like this, though map and filter certainly have their place if you're using a pre-defined function.

This gives me the desired values but I'm not sure if iterating over values of a dictionary is a good/pythonic approach.

If you want to return all values of a dictionary that meet a certain criteria, I'm not sure how you would be able to get around not iterating over the values of a dictionary.

For a filter-based approach, I would do it as:

list(filter(lambda x: x['a'] == 10, foo.values()))

There's no need for the if-else in your original code.

Answer from Karin on Stack Overflow
🌐
Reddit
reddit.com › r/learnpython › how to filter a nested dict by key?
r/learnpython on Reddit: How to filter a nested dict by key?
February 6, 2022 -

I have a nested dictionary of source words, target words, and their frequency counts. It looks like this:

src_tgt_dict = {"each":{"chaque":3}, "in-front-of":{"devant":4}, "next-to":{"à-côté-de":5}, "for":{"pour":7}, "cauliflower":{"chou-fleur":4}, "on":{"sur":2, "panda-et":2}}

I am trying to filter the dictionary so that only key-value pairs that are prepositions remain. To that end, I've written the following:

tgt_preps = set(["devant", "pour", "sur", "à"]) #set of target prepositions

src_tgt_dict = {"each":{"chaque":3}, "in-front-of":{"devant":4}, "next-to":{"à-côté-de":5}, "for":{"pour":7}, "cauliflower":{"chou-fleur":4}, "on":{"sur":2, "panda-et":2}}

new_tgt_preps = [] #list of new target prepositions

for src, d in src_tgt_dict.items(): #loop into the dictionary
    for tgt, count in d.items(): #loop into the nested dictionary
        check_prep = []
        if "-" in tgt: #check to see if hyphen occurs in the target word (this is to capture multi-word prepositions that are not in the original preposition set)
            check_prep.append(tgt[0:(tgt.index("-"))]) #if there's a hyphen, append the preceding word to the check_prep list
            for t in check_prep: 
                if t in tgt_preps: # check to see if the token preceding the hyphen is a preposition
                    new_tgt_preps.append(tgt) #if yes, append the multi-word preposition to the list of new target prepositions

tgt_preps.update(new_tgt_preps) # update the set of prepositions to include the multi-word prepositions

temp_2_src_tgt_dict = {} # create new dict for filtering
for src, d in src_tgt_dict.items(): # loop into the dictionary
    for tgt, count in d.items(): # loop into the nested dictionary
        if tgt in tgt_preps: # if the target is in the set of target prepositions
            temp_2_src_tgt_dict[tgt] = count # add to the new dict with the tgt as the key and the count as the value

When I print the new dict, I get the following:

{'devant': 4, 'pour': 7, 'sur': 2, 'à-côté-de': 5}

And it totally makes sense why I get that, because that's what I told the machine to do. But that's not my intention!

What I want is:

{"in-front-of:{"devant":4}, "for":{"pour":7}, "on":{"sur":2}, {"next-to":{"à-côté-de":5}}

I've tried to instantiate the nested dictionary by writing:

temp_2_src_tgt_dict[tgt][src] = count

but that throws up a Key Error.

Can anyone provide any suggestions or advice? Thank you in advance for your help.

Discussions

python - Filtering nested dictionaries - Stack Overflow
How to filter a nested dictionary (pythonic way) for a specific value using map or filter instead of list comprehensions? More on stackoverflow.com
🌐 stackoverflow.com
Filter nested dictionary in Python
I’m trying to remove key: value pairs from a nested dictionary within a nested dictionary, based on the value of a value within the double-nested dict. The dictionary looks something like this, and I want to filter out entire entries of people with an age under 25 years old (while I do not ... More on python.tutorialink.com
🌐 python.tutorialink.com
1
Filter nested dictionary in python based on key values - Stack Overflow
Also note that in Python 2.x, you probably want to swap in iteritems() for items(). ... Sign up to request clarification or add additional context in comments. ... I really appreciate the answer by @Lattyware. It helped me filter out a nested object and remove empty values regardless of type ... More on stackoverflow.com
🌐 stackoverflow.com
Filtering a nested (default) dict based on values
new_filtered_dict = {} for k, d in your_dict.items(): filtered = {word: count for word, count in d.items() if count >= 2} # subfiltering on count value if filtered: # filtering on having any items after subfilter new_filtered_dict[k] = filtered More on reddit.com
🌐 r/learnpython
1
1
January 28, 2022
🌐
GeeksforGeeks
geeksforgeeks.org › python › python-filter-key-from-nested-item
Python - Filter Key from Nested item - GeeksforGeeks
April 27, 2023 - Define a recursive function filter_dict() that takes in a dictionary and a query dictionary and returns a list of keys from the original dictionary that meet the filtering condition.
🌐
TutorialsPoint
tutorialspoint.com › filter-key-from-nested-item-using-python
Filter key from Nested item using Python
The built?in method pop() in Python is used to remove or return the given index value. In the following example, the program uses recursion means the function calls to function itself where inside the function the built?in function isintance() is used to check the object type and by returning the function it will use the dictionary comprehension. def filter_keys_nested_item(data, keys): if isinstance(data, dict): return {k: filter_keys_nested_item(v, keys) for k, v in data.items() if k in keys} elif isinstance(data, list): return [filter_keys_nested_item(item, keys) for item in data] else: return data # create the nested item nested_item = { "key1": "value1", "key2": { "key3": "value3", "key4": "value4" }, "key5": [ {"key6": "value6"}, {"key7": "value7"} ] } filtered_item = filter_keys_nested_item(nested_item, ["key2", "key4", "key6"]) print(filtered_item)
🌐
w3resource
w3resource.com › python-exercises › dictionary › python-data-type-dictionary-exercise-42.php
Python: Filter a dictionary based on values - w3resource
June 28, 2025 - # Iterate through the key-value pairs in 'marks' and include them in the new dictionary if the value is greater than or equal to 170. result = {key: value for (key, value) in marks.items() if value >= 170} # Print the new dictionary containing only the filtered key-value pairs. print(result) ... Original Dictionary: {'Cierra Vega': 175, 'Alden Cantrell': 180, 'Kierra Gentry': 165, 'Pierre Cox': 190} Marks greater than 170: {'Cierra Vega': 175, 'Alden Cantrell': 180, 'Pierre Cox': 190} ... Write a Python program to filter a dictionary and return only those entries where the value exceeds a given threshold.
Find elsewhere
Top answer
1 of 2
10

You can define this recursively pretty easily with a dict comprehension.

def remove_keys_with_none_values(item):
    if not hasattr(item, 'items'):
        return item
    else:
        return {key: remove_keys_with_none_values(value) for key, value in item.items() if value is not None}

Recursion isn't too optimised in Python, but given the relatively small number of nestings that are likely, I wouldn't worry.

Looking before we leap isn't too Pythonic, I think it is a better option than catching the exception - as it's likely that the value will not be a dict most of the time (it is likely we have more leaves than branches).

Also note that in Python 2.x, you probably want to swap in iteritems() for items().

2 of 2
0

I really appreciate the answer by @Lattyware. It helped me filter out a nested object and remove empty values regardless of type being dict, list, or str.

Here is what I came up with:

remove-keys-with-empty-values.py

# remove-keys-with-empty-values.py
from pprint import pprint

def remove_keys_with_empty_values(item):
  if hasattr(item, 'items'):
    return {key: remove_keys_with_empty_values(value) for key, value in item.items() if value==0 or value}
  elif isinstance(item, list):
    return [remove_keys_with_empty_values(value) for value in item if value==0 or value]
  else:
    return item

d = {
     'string': 'value',
     'integer': 10,
     'float': 0.5,
     'zero': 0,
     'empty_list': [],
     'empty_dict': {},
     'empty_string': '',
     'none': None,
    }

d['nested_dict'] = d.copy()
l = d.values()
d['nested_list'] = l

pprint({
  "DICT FILTERED": remove_keys_with_empty_values(d),
  "DICT ORIGINAL": d,
  "LIST FILTERED": remove_keys_with_empty_values(l),
  "LIST ORIGINAL": l,
})

execution

python remove-keys-with-empty-values.py
    {'DICT FILTERED': {'float': 0.5,
                       'integer': 10,
                       'nested_dict': {'float': 0.5,
                                       'integer': 10,
                                       'string': 'value',
                                       'zero': 0},
                       'nested_list': [0,
                                       'value',
                                       10,
                                       0.5,
                                       {'float': 0.5,
                                        'integer': 10,
                                        'string': 'value',
                                        'zero': 0}],
                       'string': 'value',
                       'zero': 0},
     'DICT ORIGINAL': {'empty_dict': {},
                       'empty_list': [],
                       'empty_string': '',
                       'float': 0.5,
                       'integer': 10,
                       'nested_dict': {'empty_dict': {},
                                       'empty_list': [],
                                       'empty_string': '',
                                       'float': 0.5,
                                       'integer': 10,
                                       'none': None,
                                       'string': 'value',
                                       'zero': 0},
                       'nested_list': [{},
                                       0,
                                       'value',
                                       None,
                                       [],
                                       10,
                                       0.5,
                                       '',
                                       {'empty_dict': {},
                                        'empty_list': [],
                                        'empty_string': '',
                                        'float': 0.5,
                                        'integer': 10,
                                        'none': None,
                                        'string': 'value',
                                        'zero': 0}],
                       'none': None,
                       'string': 'value',
                       'zero': 0},
     'LIST FILTERED': [0,
                       'value',
                       10,
                       0.5,
                       {'float': 0.5,
                        'integer': 10,
                        'string': 'value',
                        'zero': 0}],
     'LIST ORIGINAL': [{},
                       0,
                       'value',
                       None,
                       [],
                       10,
                       0.5,
                       '',
                       {'empty_dict': {},
                        'empty_list': [],
                        'empty_string': '',
                        'float': 0.5,
                        'integer': 10,
                        'none': None,
                        'string': 'value',
                        'zero': 0}]}
🌐
Reddit
reddit.com › r/learnpython › filtering a nested (default) dict based on values
r/learnpython on Reddit: Filtering a nested (default) dict based on values
January 28, 2022 -

Hello.

I've gotten some help from redditors on a very similar problem before, but I've modified the problem slightly.

I have a nested defaultdict, the structure of which is {'source_word_string':{'target_word_string':frequency_int}}. When (pretty) printed, it looks like this:

defaultdict(<function <lambda> at 0x10948ee50>,
            {'around': defaultdict(<class 'int'>, {'autour-de': 1}),
             'from': defaultdict(<class 'int'>, {'en': 1}),
             'in-front-of': defaultdict(<class 'int'>, {'devant': 1}),
             'on': defaultdict(<class 'int'>, {'sur': 2, 'au-bord-d’': 1}),
             'to': defaultdict(<class 'int'>, {'en': 1, 'à':3}),
             'under': defaultdict(<class 'int'>, {'sous': 1})})

I would like to delete all source-target word pairs whose frequency count is less than 2.

I would thus expect as output:

defaultdict(<function <lambda> at 0x108c57e50>,             
    {'on': defaultdict(<class 'int'>, {'sur': 2}),
    {'to': defaultdict(<class 'int'>, {'à': 3})}) 

I think I need to do two nested loops (over source words and over target words) and then write to a new filtered_dict, but I'm not sure what that looks like in practice.

Any help would be greatly appreciated. Thank you in advance.

Top answer
1 of 1
3

It's a really old question. I came across a similar problem recently.

It maybe obvious, but you are dealing with a tree in which each node has an arbitray number of children. You want to cut the subtrees that do not contain some items as nodes (not leaves). To achieve this, you are using a custom DFS: the main function returns either a subtree or None. If the value is None then you "cut" the branch.

First of all, the function dict_key_filter returns a (non empty) dict, a (non empty) list or None if no filter key was not found in the branch. To reduce complexity, you could return a sequence in every case: an empty sequence if no filter key was found, and a non empty sequence if you are still searching or you found the leaf of the tree. Your code would look like:

def dict_key_filter(obj, obj_filter):
    if isinstance(obj, dict):
        retdict = {}
        ...
        return retdict # empty or not
    elif isinstance(obj, list):
        retlist = []
        ...
        return retlist # empty or not
    else:
        return [] # obvioulsy empty

This was the easy part. Now we have to fill the dots.

The list case

Let's begin with the list case, since it is the easier to refactor:

retlist = []
for value in obj:
    child = dict_key_filter0(value, obj_filter)
    if child:
        retlist.append(child)

We can translate this into a simple list comprehension:

retlist = [dict_key_filter(value, obj_filter) for value in obj if dict_key_filter(value, obj_filter)]

The drawback is that dict_key_filter is evaluated twice. We can avoid this with a little trick (see https://stackoverflow.com/a/15812866):

retlist = [subtree for subtree in (dict_key_filter(value, obj_filter) for value in obj) if subtree]

The inner expression (dict_key_filter(value, obj_filter) for value in obj) is a generator that calls dict_key_filter once per value. But we can even do better if we build a closure of dict_key_filter:

def dict_key_filter(obj, obj_filter):
    def inner_dict_key_filter(obj): return dict_key_filter(obj, obj_filter)

    ...

    retlist = list(filter(len, map(inner_dict_key_filter, obj)))

Now we are in the functional world: map applies inner_dict_key_filter to every element of the list and then the subtrees are filtered to exclude empty subtrees (len(subtree) is true iff subtree is not empty). Now, the code looks like:

def dict_key_filter(obj, obj_filter):
    def inner_dict_key_filter(obj): return dict_key_filter(obj, obj_filter)

    if isinstance(obj, dict):
        retdict = {}
        ...
        return retdict
    elif isinstance(obj, list):
        return list(filter(len, map(inner_dict_key_filter, obj)))
    else:
        return []

If you are familiar with functional programming, the list case is readable (not quite as readable as it would be in Haskell, but still readable).

The dict case

I do not forget the dictionary-comprehension tag in your question. The first idea is to create a function to return either a whole copy of the branch or the result of the rest of the DFS.

def build_subtree(key, value):
    if key in obj_filter:
        return copy.deepcopy(value) # keep the branch
    elif isinstance(value, (dict, list)):
        return inner_dict_key_filter(value) # continue to search
    return [] # just an orphan value here

As in the list case, we do not refuse empty subtrees for now:

retdict = {}
for key, value in obj.items():
    retdict[key] = build_subtree(key, value)

We have now a perfect case for dict comprehension:

retdict = {key: build_subtree(key, value) for key, value in obj.items() if build_subtree(key, value)}

Again, we use the little trick to avoid to compute a value twice:

retdict = {key:subtree for key, subtree in ((key, build_subtree(key, value)) for key, value in obj.items()) if subtree}

But we have a little problem here: the code above is not exaclty equivalent to the original code. What if the value is 0? In the original version, we have retdict[key] = copy.deepcopy(0) but in the new version we have nothing. The 0 value is evaluated as false and filtered. And then the dict may become empty and we cut the branch wrongfully. We need another test to be sure we want to remove a value: if it's an empty list or dict, then remove it, else keep it:

def to_keep(subtree): return not (isinstance(subtree, (dict, list)) or len(subtree) == 0)

That is:

 def to_keep(subtree): return not isinstance(subtree, (dict, list)) or subtree

If you remember a bit of logic (https://en.wikipedia.org/wiki/Truth_table#Logical_implication) you can interpret this as: if subtree is a dict or a list, then it must not be empty.

Let's put the pieces together:

def dict_key_filter(obj, obj_filter):
    def inner_dict_key_filter(obj): return dict_key_filter(obj, obj_filter)
    def to_keep(subtree): return not isinstance(subtree, (dict, list)) or subtree

    def build_subtree(key, value):
        if key in obj_filter:
            return copy.deepcopy(value) # keep the branch
        elif isinstance(value, (dict, list)):
            return inner_dict_key_filter(value) # continue to search
        return [] # just an orphan value here

    if isinstance(obj, dict):
        key_subtree_pairs = ((key, build_subtree(key, value)) for key, value in obj.items())
        return {key:subtree for key, subtree in key_subtree_pairs if to_keep(subtree)}
    elif isinstance(obj, list):
        return list(filter(to_keep, map(inner_dict_key_filter, obj)))
    return []

I don't know if this is more pythonic, but it seems clearer to me.

dict1 = {
    'test1': { 'test2':[1,2] }, 
    'test3': [
        {'test6': 2}, 
        {
            'test8': { 'test9': 23 }
        }
    ],
    'test4':{'test5': 0}
}

obj_filter = ['test5' , 'test9']

print (dict_key_filter(dict1, obj_filter))
# {'test3': [{'test8': {'test9': 23}}], 'test4': {'test5': 0}}
🌐
YouTube
youtube.com › codemore
Filtering nested dictionary in Python - YouTube
Download this code from https://codegive.com Certainly! Filtering nested dictionaries in Python can be a common task when you have complex data structures an...
Published   November 25, 2023
Views   20
🌐
PyPI
pypi.org › project › sndict
sndict · PyPI
This module provides extensions to dicts in the python standard library, providing fast and clean manipulation of nested dictionary structures. This module exposes two new dict-types: NestedDict/ndict: A light-weight wrapper for dict s that provides additional functionality for operations on nested dictionary structures. StructuredNestedDict/sndict: A heavy-weight data dict -based structure for operating on hierarchical data with rich functionality for filtering and transformation across nested levels.
      » pip install sndict
    
Published   May 02, 2019
Version   0.1.2
🌐
Stack Overflow
stackoverflow.com › questions › 64147961 › filter-nested-data-from-a-dictionary
python - Filter nested data from a dictionary - Stack Overflow
my_dict = { 'user_1': {'role': 1, 'perm': 5}, 'user_2': {'role': 1, 'perm': 5}, 'user_3': {'role': 1, 'perm': 4}, 'user_4': {'role': 1, 'perm': 7}, 'user_5': {'role': 3, 'perm': 5} } def filter_dict(role,perm,dic): filtered = {} users = [k for k in dic.keys() if dic[k]['role'] == int(role) and dic[k]['perm'] == int(perm)] for user in users: filtered[user] = dic[user] return filtered ... You kinda want to turn the whole thing inside out as you build an index. Then you can use the index to construct the dictionaries you want:
Top answer
1 of 1
2

I have coded a custom filter method:

def customFilter(all_assets, search_attribute, search_attribute_value):
    res = []
    for asset in all_assets:
        if asset:
            attributes = asset["metadata"]["tags"][1]["attributes"]
            if attributes and search_attribute in attributes:
                if search_attribute_value == attributes[search_attribute]:
                    res.append(asset)
    return res

Lets test it:

all_assets = [
    {
        "dateListed": 58391,
        "id": "118572",
        "metadata": {
            "files": [],
            "mediaType": "image/png",
            "name": "The three",
            "tags": [
                {"right": "101 Galaxy"},
                {
                    "attributes": {
                        "Background": "Mars",
                        "Body": "Rough",
                        "Face": "Dumb",
                        "Headwear": "Helmet",
                    }
                },
            ],
            "thumbnail": "something",
        },
        "Session": None,
        "police": "pewpew",
        "verified": {"project": "Thes", "verified": True},
    },
    {
        "dateListed": 430298239,
        "id": "1191281",
        "metadata": {
            "files": [],
            "mediaType": "image/png",
            "name": "TheOne",
            "tags": [
                {"right": "101 Galaxy"},
                {
                    "attributes": {
                        "Background": "Star",
                        "Body": "Smooth",
                        "Face": "Fresh",
                        "Headwear": "Cap",
                    }
                },
            ],
            "thumbnail": "something",
        },
        "Session": None,
        "police": "pewpew",
        "verified": {"project": "Thes", "verified": True},
    },
]

search_attribute = "Background"
search_attribute_value = "Star"

print(customFilter(all_assets, search_attribute, search_attribute_value))

Output:

[{'dateListed': 430298239, 'id': '1191281', 'metadata': {'files': [], 'mediaType': 'image/png', 'name': 'TheOne', 'tags': [{'right': '101 Galaxy'}, {'attributes': {'Background': 'Star', 'Body': 'Smooth', 'Face': 'Fresh', 'Headwear': 'Cap'}}], 'thumbnail': 'something'}, 'Session': None, 'police': 'pewpew', 'verified': {'project': 'Thes', 'verified': True}}]
🌐
GitHub
gist.github.com › douglasmiranda › 5127251
Find all occurences of a key in nested python dictionaries and lists - http://stackoverflow.com/questions/9807634/find-all-occurences-of-a-key-in-nested-python-dictionaries-and-lists · GitHub
Nice! if any of your nested lists contains primitives (e.g, strings) and not always dicts, it will error out. In that case add a check for it and skip the element (added line 2 before last): def find(key, dictionary): for k, v in dictionary.iteritems(): if k == key: yield v elif isinstance(v, dict): for result in find(key, v): yield result elif isinstance(v, list): for d in v: if isinstance(d, dict): for result in find(key, d): yield result ... Python3 users should replace dictionary.iteritems() with dictionary.items().