Python: Apply function to values in nested dictionary

Just to expand on vaultah's answer, if one of your elements can be a list, and you'd like to handle those too:

import collections

def map_nested_dicts_modify(ob, func):
for k, v in ob.iteritems():
    if isinstance(v, collections.Mapping):
        map_nested_dicts_modify(v, func)
    elif isinstance(v, list):
        ob[k] = map(func, v)
    else:
        ob[k] = func(v)

Visit all nested values recursively:

import collections

def map_nested_dicts(ob, func):
    if isinstance(ob, collections.Mapping):
        return {k: map_nested_dicts(v, func) for k, v in ob.iteritems()}
    else:
        return func(ob)

map_nested_dicts(x, lambda v: v + 7)
# Creates a new dict object:
#    {'a': 8, 'b': {'c': 13, 'g': {'h': 10, 'i': 16}, 'd': 14}, 'e': {'f': 10}}

In some cases it's desired to modify the original dict object (to avoid re-creating it):

import collections

def map_nested_dicts_modify(ob, func):
    for k, v in ob.iteritems():
        if isinstance(v, collections.Mapping):
            map_nested_dicts_modify(v, func)
        else:
            ob[k] = func(v)

map_nested_dicts_modify(x, lambda v: v + 7)
# x is now
#    {'a': 8, 'b': {'c': 13, 'g': {'h': 10, 'i': 16}, 'd': 14}, 'e': {'f': 10}}

If you're using Python 3:

  • replace dict.iteritems with dict.items

  • replace import collections with import collections.abc

  • replace collections.Mapping with collections.abc.Mapping