All the Way Down
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
- L4
Problem
A config export arrives as a list whose entries are either plain values or further lists, nested to arbitrary depth with no fixed structure. Collapse it into a single flat list holding every leaf value in left-to-right order. Treat strings as leaf values, not as sequences to descend into.
However deep it nests, every leaf belongs on one line.
Example 1
Input:
nested = [1,[2,[3,4]],[5,[6,7]]]
Output:
[1,2,3,4,5,6,7]
Example 2
Input:
nested = ["a",["bc",["d"]]]
Output:
["a","bc","d"]
Worked solution and explanation
What this really is
Strip the costume off and this is a tree traversal wearing a list. Every value with brackets around it is an internal node; the numbers and strings you actually want are the leaves. Once you see it that way, the whole problem collapses to one decision made at every element: is this a branch I descend into, or a leaf I keep? The trap is the definition of 'leaf'. A string is iterable, so the lazy 'can I loop over it?' test walks straight into 'abc' and hands you back 'a', 'b', 'c'. That is the single mistake that separates a clean answer from a buggy one.
Building it
Step 1: One ordered pass
Walk the list once, in order, and ask the leaf-vs-branch question per element. Left-to-right iteration is what preserves output order for free; you never sort or reverse anything.
Step 2: Recurse and splice
When the element is a list, call yourself on it. The recursive call returns an already-flat list, so extend the accumulator with it. Using extend (not a nested append loop) keeps the splice in one readable line at the same cost.
Step 3: Collect leaves whole
Otherwise the element is a leaf: append it as-is. Numbers, strings, anything non-list lands here untouched.
The solution
def deep_flatten(nested):
result = []
for item in nested:
if isinstance(item, list):
result.extend(deep_flatten(item))
else:
result.append(item)
return resultOne list check per element; recursion handles arbitrary depth.
- Naive iterable check
- if hasattr(item, '__iter__'): recurse. Looks general, but strings are iterable, so 'bc' silently explodes into 'b', 'c' and the output is wrong in a way the simple test cases may not catch.
- List check
- if isinstance(item, list): recurse. Descends only into the one container the problem cares about. Strings, tuples, and dicts are all kept as single leaf values, which is exactly the contract.
Common follow-up questions
- What if the nesting depth could exceed Python's recursion limit? (Tests iterative flattening with an explicit stack.)
- How would you handle dicts nested inside the lists? (Tests refining the container check so dicts are flattened by value rather than descended like lists.)
- What if tuples and sets also counted as containers to flatten? (Tests broadening the container check to isinstance(item, (list, tuple, set)) while still excluding strings.)