datarekha

How do you flatten a nested list in Python, and how does the approach differ for one level deep versus arbitrarily deep nesting?

The short answer

For a single level of nesting, a list comprehension or itertools.chain.from_iterable is idiomatic and O(n). For arbitrary depth, recursion or an explicit stack is required. The right choice depends on whether the structure is known at write time.

How to think about it

The first move is a clarifying question: “Is this always one level deep, or can the nesting go arbitrarily deep?” Asking it shows you think about generality — and the answer genuinely changes the tool. One level has elegant O(n) idioms; arbitrary depth needs recursion, and naming the stack concern is what impresses.

One level deep

For [[1, 2], [3, 4], [5]], two clean O(n) options:

# List comprehension — most readable
nested = [[1, 2, 3], [4, 5], [6]]
flat = [x for sublist in nested for x in sublist]    # [1, 2, 3, 4, 5, 6]

# itertools.chain.from_iterable — lazy, best for large data
import itertools
flat = list(itertools.chain.from_iterable(nested))   # [1, 2, 3, 4, 5, 6]

chain.from_iterable streams elements without building intermediates, so it’s the memory-friendly choice on big inputs.

A worked example — including arbitrary depth

For unknown depth the cleanest answer is a recursive generator: yield from both recurses and hands the generator protocol back to the caller, so you get one iterator across every level without copying:

import itertools

nested_1 = [[1, 2, 3], [4, 5], [6]]
print("List comp      :", [x for sub in nested_1 for x in sub])
print("chain.from_iter:", list(itertools.chain.from_iterable(nested_1)))

# Arbitrary depth: recurse with a generator
def flatten(seq):
    for item in seq:
        if isinstance(item, list):
            yield from flatten(item)     # recurse AND delegate the generator
        else:
            yield item

deep = [1, [2, [3, [4, [5]]], 6], 7]
print("Deep flatten   :", list(flatten(deep)))

# The "clever" one-liner that's secretly O(n^2)
small = [[1, 2], [3, 4], [5]]
print("sum trick      :", sum(small, []))
List comp      : [1, 2, 3, 4, 5, 6]
chain.from_iter: [1, 2, 3, 4, 5, 6]
Deep flatten   : [1, 2, 3, 4, 5, 6, 7]
sum trick      : [1, 2, 3, 4, 5]

The flatten generator handled five levels of nesting and emitted a clean 1..7. The magic is yield from flatten(item): it dives into the sublist and delegates the iteration, so the caller drives a single stream and memory stays O(depth), not O(total elements). (To also flatten tuples, widen the check to isinstance(item, (list, tuple)).)

Learn it properly Lists

Keep practising

All Python questions

Explore further

Skip to content