Explain Codes LogoExplain Codes Logo

Flatten an irregular (arbitrarily nested) list of lists

python
generator-functions
iterable-types
best-practices
Anton ShumikhinbyAnton Shumikhin·Jan 23, 2025
TLDR

Delve into recursive functions and turn a nested list into a single-layer list without breaking a sweat:

def flatten(lst): # Am I a joke to you? Let's unravel this mystery (a.k.a. list)! return [item for sublist in lst for item in (flatten(sublist) if isinstance(sublist, list) else [sublist])] # Apply the function (demo data borrowed from The Matrix): print(flatten([1, [2, [3, 4], 5], 6, [[7], [8, 9]]])) # Output: [1, 2, 3, 4, 5, 6, 7, 8, 9]

Now go ahead, apply this magic spell (a.k.a. code snippet) to flatten any level of list complication.

Python-oriented techniques for flattening

Generator functions: for the performance buffs

Boost performance with generators that feed items one by one:

def gen_flatten(iterable): # Look mum, I am going through walls (nested layers)! for element in iterable: if isinstance(element, list): yield from gen_flatten(element) # Unleash the kraken (nested items)! else: yield element # Victory screech! # Usage that does not involve an AI overthrow: print(list(gen_flatten([1, [2, [3, 4], 5], 6, [[7], [8, 9]]])))

Iterable types: more than just lists

Lists aren't everything. Tuples drop by too. Handle them well:

from collections.abc import Iterable def iterable_flatten(iterable): # More levels than your favorite MMORPG: for element in iterable: if isinstance(element, Iterable) and not isinstance(element, (str, bytes)): yield from iterable_flatten(element) # Nesting? Pfft, easy! else: yield element # Aannnnd... it's out! # Example - even tuples aren't safe! print(list(iterable_flatten([1, (2, [3, 4]), 5, 6, [[7], [8, 9]]])))

Real world prep: edge cases

Empty sublists and non-iterables, beware. We handle you too:

def safe_flatten(iterable): for element in iterable: if isinstance(element, Iterable) and not isinstance(element, (str, bytes)): yield from safe_flatten(element) # You were at home, now you're here. elif element: # Did I hear someone mention empty sublists? Not today! yield element

Deep explorations in flattening

Iterable checks: Deciphering the magic incantation

In the method, isinstance(element, Iterable), we inspect if we can iterate over objects and avoid splitting strings into characters by excluding string-like objects.

In-place flattening: For the brave souls only

In-place flattening is when you live life on the edge: modify original lists to conserve memory. Handle with care!

def flatten_inplace(lst): # As you wish, your majesty, no new lists! i = 0 while i < len(lst): while isinstance(lst[i], list): lst[i:i+1] = lst[i] i += 1 # Example usage: Use with caution! Memory preservation comes at a price. my_list = [1, [2, [3, 4]], 5] flatten_inplace(my_list) print(my_list) # Output: [1, 2, 3, 4, 5]

Recursive vs iterative flattening: Choose your fighter

Recursive flattening is great for readability and dealing with deeply nested lists. But beware, there's a limit to your recursion depth in Python. For ultra-deep nests, bring in the iterative approach!