Python: cómo aplanar una lista de listas

En este tutorial, repasaremos ejemplos de cómo aplanar una lista 2D (lista de listas) en una lista. Usaremos bucles for, listas de comprensión, algoritmos recursivos, así como bibliotecas como Numpy y functools.

Introducción

Una lista es la estructura de datos más flexible en Python. Mientras que una lista 2D, comúnmente conocida como lista de listas, es un objeto de lista en el que cada elemento es una lista en sí mismo, por ejemplo: [[1,2,3], [4,5,6], [7 ,8,9]].

Aplanar una lista de listas implica convertir una lista 2D en una lista 1D al anidar cada elemento de la lista almacenado en la lista de listas, es decir, convertir [[1, 2, 3], [4, 5, 6], [ 7, 8, 9]] en [1, 2, 3, 4, 5, 6, 7, 8, 9] .

El proceso de aplanamiento se puede realizar utilizando bucles for anidados, listas por comprensión, recursividad, funciones integradas o importando bibliotecas en Python, según la regularidad y profundidad de las listas anidadas.

Tipos de listas anidadas

Dado que Python tiene un tipo débil, puede encontrar listas de listas regulares e irregulares.

Lista regular de listas

Cada elemento de esta lista es una sublista, por lo que se adhiere a la uniformidad del tipo de elemento.
Ejemplo: [[1, 2, 3], [4, 5, 6], [7, 8, 9]] es una lista regular de listas como [1, 2, 3], [4, 5, 6], [7, 8, 9] es de tipo lista.

Lista irregular de listas

Cada elemento de esta lista es una sublista o un elemento que no pertenece a la lista (por ejemplo, un número entero o una cadena). Por lo tanto, existe una irregularidad en cuanto al tipo de elemento. Ejemplo: [[1, 2, 3], [4, 5], 6] donde [1, 2, 3] y [4, 5] son del tipo lista y 6 es de tipo int.

Aplanar lista de listas mediante bucles for anidados

Este es un enfoque de fuerza bruta para obtener una lista plana seleccionando cada elemento de la lista de listas y colocándolo en una lista 1D.

El código es intuitivo como se muestra a continuación y funciona tanto para listas de listas regulares como irregulares:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
def flatten_list(_2d_list):
    flat_list = []
    # Iterate through the outer list
    for element in _2d_list:
        if type(element) is list:
            # If the element is of type list, iterate through the sublist
            for item in element:
                flat_list.append(item)
        else:
            flat_list.append(element)
    return flat_list

nested_list = [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10]]
print('Original List', nested_list)
print('Transformed Flat List', flatten_list(nested_list))

Esto resulta en:

1
2
Original List [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10]]
Transformed Flat List [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Aplanar lista de listas usando una comprensión de lista

Este enfoque proporciona una solución elegante pero menos intuitiva para crear una lista plana basada en una lista 2D existente:

1
2
3
4
regular_list = [[1, 2, 3, 4], [5, 6, 7], [8, 9]]
flat_list = [item for sublist in regular_list for item in sublist]
print('Original list', regular_list)
print('Transformed list', flat_list)

Lo que daría como resultado lo siguiente:

1
2
Original list [[1, 2, 3, 4], [5, 6, 7], [8, 9]]
Transformed list [1, 2, 3, 4, 5, 6, 7, 8, 9]

Aplanar lista de listas recursivamente

La lista 2D también se puede aplanar recursivamente. La implementación a continuación funciona tanto para listas de listas regulares como irregulares:

1
2
3
4
5
6
7
8
9
def flatten(list_of_lists):
    if len(list_of_lists) == 0:
        return list_of_lists
    if isinstance(list_of_lists[0], list):
        return flatten(list_of_lists[0]) + flatten(list_of_lists[1:])
    return list_of_lists[:1] + flatten(list_of_lists[1:])


print(flatten([[1, 2, 3, 4], [5, 6, 7], [8, 9], 10]))

Lo que nos daría:

1
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Usando bibliotecas

También puede confiar en la ayuda de las bibliotecas de Pyhon para esta tarea.

Aplanar lista de listas usando functools (reduce() e iconcat())

La función iconcat() realiza la operación básica de concatenación y se aplica acumulativamente a los elementos de una lista de listas, de izquierda a derecha, para reducirla a una sola lista:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
import functools
import operator
regular_list = []

# Transform irregular 2D list into a regular one.
def transform(nested_list):
    for ele in nested_list:
        if type(ele) is list:
            regular_list.append(ele)
        else:
            regular_list.append([ele])
    return regular_list


irregular_list = [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10], 11]
regular_2D_list = transform(irregular_list)
print('Original list', irregular_list)
print('Transformed list', functools.reduce(operator.iconcat, regular_2D_list, []))

Lo que nos daría el resultado deseado:

1
2
Original list [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10], 11]
Transformed list [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

Aplanar la lista de listas usando itertools (chain())

Este enfoque es ideal para transformar una lista 2D en una sola lista plana, ya que trata las secuencias consecutivas como una sola secuencia mediante la iteración a través del iterable pasado como argumento de manera secuencial.

1
2
3
4
5
6
7
import itertools

regular_list = [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10]]
flat_list = list(itertools.chain(*regular_list))

print('Original list', regular_list)
print('Transformed list', flat_list)

Nuevamente, esto nos daría una lista aplanada como salida:

1
2
Original list [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10]]
Transformed list [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Aplanar la lista de listas usando numpy (concatenate() y flat())

Numpy ofrece operaciones comunes que incluyen la concatenación de matrices 2D regulares en filas o columnas. También estamos usando el atributo plano para obtener un iterador 1D sobre la matriz para lograr nuestro objetivo. Sin embargo, este enfoque es relativamente lento:

1
2
3
4
5
6
7
8
import numpy

regular_list = [[1, 2, 3, 4], [5, 6, 7], [8, 9]]

flat_list = list(numpy.concatenate(regular_list).flat)

print('Original list', regular_list)
print('Transformed list', flat_list)

Lo que nos da la salida deseada:

1
2
Original list [[1, 2, 3, 4], [5, 6, 7], [8, 9]]
Transformed list [1, 2, 3, 4, 5, 6, 7, 8, 9]

Uso de funciones integradas {#uso de funciones integradas}

La tarea de aplanar también se puede realizar mediante el uso de funciones integradas que ofrece Python.

Aplanar lista de listas usando sum

Sumar sobre listas internas es otra solución. La función tiene dos parámetros: iterable que es una lista de listas y start que es una lista vacía en nuestro caso que sirve como la lista plana inicial a la que se agregan elementos de las sublistas internas.

Este enfoque es conveniente ya que no tiene que importar nada, pero es más lento que las funciones itertools() y chain() cuando el número de sublistas es grande:

1
2
3
4
5
6
regular_list = [[1, 2, 3, 4], [5, 6, 7], [8, 9]]

flat_list = sum(regular_list, [])

print('Original list', regular_list)
print('Transformed list', flat_list)

Con la salida:

1
2
Original list [[1, 2, 3, 4], [5, 6, 7], [8, 9]]
Transformed list [1, 2, 3, 4, 5, 6, 7, 8, 9]

Aplanar lista de listas usando Lambda

Una función anónima se puede definir usando la palabra clave lambda. La lista regular/irregular se pasa como argumento a esta función anónima y la evaluación de la expresión se realiza para obtener una lista 1D plana:

1
2
3
4
5
6
7
irregular_list = [[1, 2, 3], [3, 6, 7], [7, 5, 4],7]

# Using lambda arguments: expression
flatten_list = lambda irregular_list:[element for item in irregular_list for element in flatten_list(item)] if type(irregular_list) is list else [irregular_list]

print("Original list ", irregular_list)
print("Transformed List ", flatten_list(irregular_list))

De nuevo obtendríamos el resultado deseado:

1
2
Original list  [[1, 2, 3], [3, 6, 7], [7, 5, 4], 7]
Transformed List  [1, 2, 3, 3, 6, 7, 7, 5, 4, 7]

Conclusión

En este artículo, proporcionamos una extensa lista de formas en que podemos completar la tarea de aplanar una lista de listas en Python.