Flattening a list, the process of converting a nested list into a single-level list, is a common task in Python. This article explores various techniques for achieving this, categorizing them by their depth of flattening: shallow and deep.
Table of Contents
Shallow Flattening
Shallow flattening only removes one level of nesting. It’s ideal when you have a list of lists, but those inner lists don’t contain further nested structures. Two efficient methods exist:
List Comprehension: This provides a concise and readable solution:
nested_list = [[1, 2, 3], [4, 5], [6]]
flat_list = [item for sublist in nested_list for item in sublist]
print(flat_list) # Output: [1, 2, 3, 4, 5, 6]
itertools.chain.from_iterable
: For larger lists, this approach offers better performance due to its optimized iteration:
from itertools import chain
nested_list = [[1, 2, 3], [4, 5], [6]]
flat_list = list(chain.from_iterable(nested_list))
print(flat_list) # Output: [1, 2, 3, 4, 5, 6]
Limitations: Shallow flattening fails to fully flatten lists with nested lists within nested lists. For instance:
nested_list = [[1, 2, [3, 4]], [5, 6]]
flat_list = [item for sublist in nested_list for item in sublist]
print(flat_list) # Output: [1, 2, [3, 4], 5, 6]
The inner list [3, 4]
remains nested.
Deep Flattening
Deep flattening recursively handles nested lists of any depth. Two primary approaches exist:
Recursive Function: This elegant solution uses recursion to traverse the nested structure:
def flatten(nested_list):
flat_list = []
for item in nested_list:
if isinstance(item, list):
flat_list.extend(flatten(item))
else:
flat_list.append(item)
return flat_list
nested_list = [[1, 2, [3, 4]], [5, 6, [7, [8, 9]]]]
flat_list = flatten(nested_list)
print(flat_list) # Output: [1, 2, 3, 4, 5, 6, 7, 8, 9]
Iterative Approach (using a stack): Recursion can lead to stack overflow errors with extremely deep nesting. An iterative approach using a stack provides robustness:
def flatten_iterative(nested_list):
flat_list = []
stack = [nested_list]
while stack:
current = stack.pop()
if isinstance(current, list):
stack.extend(current)
else:
flat_list.append(current)
return flat_list
nested_list = [[1, 2, [3, 4]], [5, 6, [7, [8, 9]]]]
flat_list = flatten_iterative(nested_list)
print(flat_list) # Output: [1, 2, 3, 4, 5, 6, 7, 8, 9]
Conclusion
The choice between shallow and deep flattening depends entirely on the structure of your nested lists. Shallow flattening is sufficient for single-level nesting and offers concise, efficient solutions. However, for arbitrarily nested lists, deep flattening, preferably using the iterative stack-based approach for robustness, is necessary.