Erlang y Ruby vienen con funciones para aplanar matrices. Parece una herramienta tan simple y útil para agregar a un idioma. Uno podría hacer esto:
>>> mess = [[1, [2]], 3, [[[4, 5]], 6]]
>>> mess.flatten()
[1, 2, 3, 4, 5, 6]
O incluso:
>>> import itertools
>>> mess = [[1, [2]], 3, [[[4, 5]], 6]]
>>> list(itertools.flatten(mess))
[1, 2, 3, 4, 5, 6]
En cambio, en Python, uno tiene que pasar por la molestia de escribir una función para aplanar matrices desde cero. Esto me parece tonto, aplanar matrices es algo muy común. Es como tener que escribir una función personalizada para concatenar dos matrices.
He buscado en Google esto infructuosamente, así que pregunto aquí; ¿Hay alguna razón particular por la cual un lenguaje maduro como Python 3, que viene con cientos de miles de baterías diferentes incluidas, no proporcione un método simple para aplanar matrices? ¿Se ha discutido y rechazado la idea de incluir tal función en algún momento?
fuente
extend
pero aplanar habría sido mucho más elegante. Sin embargo, me equivoco si este patrón es lo suficientemente común como para justificar haber aplanado en la biblioteca estándar.Respuestas:
Las propuestas para
flatten
agregar una función a la biblioteca estándar aparecen de vez en cuando en las listas de correo python-dev y python-ideas . Los desarrolladores de Python suelen responder con los siguientes puntos:Un aplanamiento de un nivel (que convierte un iterable de iterables en un único iterable) es una expresión trivial de una línea
(x for y in z for x in y)
y, en cualquier caso, ya está en la biblioteca estándar bajo el nombreitertools.chain.from_iterable
.¿Cuáles son los casos de uso para un aplanamiento multinivel de uso general? ¿Son realmente lo suficientemente convincentes como para que la función se agregue a la biblioteca estándar?
¿Cómo decidiría un aplanamiento multinivel de propósito general cuándo aplanar y cuándo dejar solo? Puede pensar que una regla como "aplanar cualquier cosa que admita la interfaz iterable" funcionaría, pero eso conduciría a un bucle infinito
flatten('a')
.Ver por ejemplo Raymond Hettinger :
fuente
flatten
se puede definir comolambda z: [x for y in z for x in y]
.flatten
método. La implementación de este método debe recurrir recursivamenteflatten
a su subcomponente, si el objeto es un compuesto. Desafortunadamente, AFAIK no todos los valores son un objeto en Python. Sin embargo, en Ruby debería funcionar.Viene con tal método pero no lo llama aplanar. Se llama " cadena ". Devuelve un iterador en el que luego deberías usar la función list () para volver a convertirlo en una lista. Si no desea usar un *, puede usar la segunda versión "from_iterator". Funciona igual en Python 3. Fallará si la entrada de la lista no es una lista de listas.
Hubo una vez un método de aplanamiento en el módulo compiler.ast, pero esto fue desaprobado en 2.6 y luego eliminado en 3.0. La recursividad de profundidad arbitraria, necesaria para listas anidadas arbitrariamente, no funciona bien con la profundidad de recursión máxima conservadora de Python. El razonamiento para la eliminación del compilador se debió en gran medida a que era un desastre . El compilador se convirtió en ast, pero se quedó atrás.
La profundidad arbitraria se puede lograr con las matrices de numpy y el aplanamiento de esa biblioteca.
fuente
chain.from_iterator
función, como dijiste, solo se puede usar para aplanar listas bidimensionales. Una función realmente plana , que acepta cualquier cantidad de listas anidadas y devuelve una lista unidimensional, aún sería enormemente útil en muchos casos (al menos en mi opinión)... tal vez porque no es tan difícil escribir uno tú mismo
... y luego aplanar todo lo que quieras :)
fuente