This problem was asked by Stripe.

Write a function to flatten a nested dictionary. Namespace the keys with a period.

For example, given the following dictionary:

{
    "key": 3,
    "foo": {
        "a": 5,
        "bar": {
            "baz": 8
        }
    }
}

it should become:

{
    "key": 3,
    "foo.a": 5,
    "foo.bar.baz": 8
}

You can assume keys do not contain dots in them, i.e. no clobbering will occur

Working With a Python Dictionary

What can you do with dictionaries once you have created them? Well, you can access elements, update values, delete elements, etc.

It is best to think of a dictionary as a set of key: value pairs, with the requirement that the keys are unique (within one dictionary). A pair of braces creates an empty dictionary: {}. Placing a comma-separated list of key:value pairs within the braces adds initial key:value pairs to the dictionary; this is also the way dictionaries are written on output.

The main operations on a dictionary are storing a value with some key and extracting the value given the key. It is also possible to delete a key:value pair with del. If you store using a key that is already in use, the old value associated with that key is forgotten. It is an error to extract a value using a non-existent key.

Looping Techniques

When looping through dictionaries, the key and corresponding value can be retrieved at the same time using the items() method.

>>> req = {
    "key": 3,
    "foo": {
        "a": 5,
        "bar": {
            "baz": 8
        }
    }
}
>>> for k, v in req.items():
...     print(k, v)
...
key 3
foo {
        "a": 5,
        "bar": {
            "baz": 8
        }

When looping through a sequence, the position index and corresponding value can be retrieved at the same time using the enumerate() function.

Let's solve the problem we described above

def flatten_dict(req, res={}, base_key=None):
    """
        Function to flatten keys of dictionary
    """
    if not isinstance(req, dict):
        return
    else:
        actual_key = f"{base_key}." if base_key is not None else ""

        for key, value in req.items():
            if isinstance(value, dict):
                res = flatten_dict(value, res, actual_key+key)
            else:
                res[f"{actual_key}{key}"] = value
    
    return res

Calling the required function we get

# input
req = {
    "key": 3,
    "foo": {
        "a": 5,
        "bar": {
            "baz": 8
        }
    }
}

result = flatten_dict(req)

print(result)

{
    "key": 3,
    "foo.a": 5,
    "foo.bar.baz": 8
}