Single File

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

Domain
Python
Difficulty
easy
Seniority
L3
Asked in
Meta

Problem

You are given feed, a list of content entries. Each entry is either an item or a sub-list of entries, and sub-lists can nest to any depth. Any value that is not a list is a single item. Return all the items as one flat list.

However deep the nesting, every voice arrives in its own turn.

Example 1

Input:

feed = [[1,2],[3,[4,5]],6]

Output:

[1,2,3,4,5,6]

Example 2

Input:

feed = ["top",["trending",["sports","tech"]],"latest"]

Output:

["top","trending","sports","tech","latest"]

Worked solution and explanation

What you are really being asked

Strip the feed costume off and this is depth-first leaf collection: walk the structure, and every value that is not itself a list is a leaf you keep, in the order you meet it. The recursion is the easy part. The thing that separates a clean pass from a quietly broken one is the type test. The tempting move is to ask 'can I iterate this?' and recurse when the answer is yes. That instinct detonates on the first string: 'tech' is perfectly iterable, so you descend into it and hand back its characters. Branch on isinstance(item, list) specifically and the trap never opens.


Where it bites

isinstance(item, list)
Recurses only into real sub-lists. A string like 'tech' is not a list, so it lands in the result untouched. This is the behavior you want.
isinstance(item, Iterable)
Treats every iterable as nestable. 'tech' is iterable, so you recurse into it and get back 't', 'e', 'c', 'h'. The feed silently shreds every string leaf.

Building it

Step 1: Walk one level at a time

Loop over the entries at the current depth. You do not need to know how deep the feed goes; recursion handles depth for you, so this loop only ever reasons about one level at a time.

Step 2: Branch on list, never on iterable

For each entry, ask only one question: is it a list? If yes, it is more structure to descend into. If no, it is a leaf (string included) and goes straight into the result. Widening this test to any-iterable is exactly how strings get shredded.

Step 3: Splice children in place

Recurse on a sub-list and extend the result with whatever comes back. Because you extend in iteration order, the depth-first left-to-right ordering falls out for free, with no sorting or post-processing needed.

Recursive depth-first flattening
def flatten(feed):
    result = []
    for item in feed:
        if isinstance(item, list):
            result.extend(flatten(item))
        else:
            result.append(item)
    return result

Common follow-up questions