The Deep Config

A medium Python interview practice problem on DataDriven. Write the Python and run it against test cases, with instant feedback.

Domain
Python
Difficulty
medium
Seniority
L5
Asked in
Amazon

Problem

A service loads its settings as a nested dict, where each level of nesting groups a section with its sub-settings and the leaves (non-dict values) are the actual settings. Collapse config into a single-level dict whose keys are the full path from the top down to each leaf, with the path segments joined by '.'. An empty input comes back empty, and a section that holds no leaves contributes nothing.

Every setting has a path. Trace it down to the value.

Example 1

Input:

config = {"server":{"host":"localhost","port":8080}}

Output:

{"server.host":"localhost","server.port":8080}

Example 2

Input:

config = {"db":{"host":"rds","pool":{"max":20}},"region":"us-east"}

Output:

{"db.host":"rds","db.pool.max":20,"region":"us-east"}

Worked solution and explanation

What this really is

Strip the config-management costume off and this is a depth-first walk of a tree where every root-to-leaf path becomes one key. The skill being probed: can you carry the path-so-far down the descent and emit ONLY at the leaves? Anyone can loop the top level. The separation is whether you recurse with the accumulated prefix instead of hardcoding two or three levels, and whether you resist writing an entry for the intermediate dicts. Get that wrong and you either cap out at a fixed depth or pollute the output with half-formed paths that point at sub-dicts.


How to get there

Step 1: Branch on dict vs leaf

Walk the keys at the current level. The only decision per entry is the shape of the value: a dict means there is more path to descend, anything else is a leaf you record.

Step 2: Carry the prefix down, not a leading dot

Thread the path-so-far through the recursion as a prefix. At the root the prefix is empty, so the first segment carries no leading dot; below the root you glue parent and child with a single '.'. This is the one place beginners trip: an unguarded prefix + '.' + key yields '.server' at the top.

Step 3: Merge sub-results, record at leaves

Recurse into dicts and merge what comes back; record the value only when it is not a dict. An empty section recurses into nothing and merges nothing, so it silently drops out of the output, which is exactly the contract.


The solution

Recursive descent with prefix tracking
def the_deep_config(config, prefix=""):
    result = {}
    for key, value in config.items():
        full_key = f"{prefix}.{key}" if prefix else key
        if isinstance(value, dict):
            result.update(the_deep_config(value, full_key))
        else:
            result[full_key] = value
    return result

The default prefix lets the grader call the_deep_config(config) with one argument while recursion supplies the second.

Fixed-depth handling
Nested loops, one per level, that assume two or three tiers. Reads fine on the sample, then silently truncates the moment a config nests four deep.
Recursive prefix
One function that descends as far as the data goes, gluing the path as it falls. Depth is whatever the input is; nothing is hardcoded.

Common follow-up questions