Achatar uma lista, o processo de converter uma lista aninhada em uma lista de nível único, é uma tarefa comum em Python. Este artigo explora várias técnicas para alcançar isso, categorizando-as por sua profundidade de achatamento: superficial e profundo.
Sumário
Achatamento Superficial
O achatamento superficial remove apenas um nível de aninhamento. É ideal quando você tem uma lista de listas, mas essas listas internas não contêm estruturas aninhadas adicionais. Existem dois métodos eficientes:
List Comprehension: Isso fornece uma solução concisa e legível:
nested_list = [[1, 2, 3], [4, 5], [6]]
flat_list = [item for sublist in nested_list for item in sublist]
print(flat_list) # Saída: [1, 2, 3, 4, 5, 6]
itertools.chain.from_iterable
: Para listas maiores, esta abordagem oferece melhor desempenho devido à sua iteração otimizada:
from itertools import chain
nested_list = [[1, 2, 3], [4, 5], [6]]
flat_list = list(chain.from_iterable(nested_list))
print(flat_list) # Saída: [1, 2, 3, 4, 5, 6]
Limitações: O achatamento superficial não consegue achatar completamente listas com listas aninhadas dentro de listas aninhadas. Por exemplo:
nested_list = [[1, 2, [3, 4]], [5, 6]]
flat_list = [item for sublist in nested_list for item in sublist]
print(flat_list) # Saída: [1, 2, [3, 4], 5, 6]
A lista interna [3, 4]
permanece aninhada.
Achatamento Profundo
O achatamento profundo lida recursivamente com listas aninhadas de qualquer profundidade. Existem duas abordagens principais:
Função Recursiva: Esta solução elegante usa recursão para percorrer a estrutura aninhada:
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) # Saída: [1, 2, 3, 4, 5, 6, 7, 8, 9]
Abordagem Iterativa (usando uma pilha): A recursão pode levar a erros de estouro de pilha com aninhamento extremamente profundo. Uma abordagem iterativa usando uma pilha fornece robustez:
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) # Saída: [1, 2, 3, 4, 5, 6, 7, 8, 9]
Conclusão
A escolha entre o achatamento superficial e o profundo depende inteiramente da estrutura de suas listas aninhadas. O achatamento superficial é suficiente para aninhamento de nível único e oferece soluções concisas e eficientes. No entanto, para listas arbitrariamente aninhadas, o achatamento profundo, preferencialmente usando a abordagem iterativa baseada em pilha para robustez, é necessário.