Aplanando una lista superficial en Python

| | | | | | | | | | | | | |

¿Existe una manera simple de aplanar una lista de iterables con una lista de comprensión o, en su defecto, cuál considerarían que es la mejor manera de aplanar una lista superficial como esta, equilibrando el rendimiento y la legibilidad?

Traté de aplanar dicha lista con una comprensión de lista anidada, como esta:

[imagen para imagen en elemento de menú para elemento de menú en lista_de_elementos_de_menú] 

Pero me meto en problemas con la variedad NameError allí, porque el name "menuitem" no está definido. Después de buscar en Google y buscar en Stack Overflow, obtuve los resultados deseados con una instrucción reduce:

reduce(list.__add__, map(lambda x: list(x ), list_of_menuitems)) 

Pero este método es bastante ilegible porque necesito esa llamada a list(x) porque x es un Django QuerySet object.

Conclusión:

Gracias a todos los que contribuyeron con esta pregunta. Aquí hay un resumen de lo que aprendí. También estoy haciendo de esto un wiki comunitario en caso de que otros quieran agregar o corregir estas observaciones.

Mi declaración de reducción original es redundante y está mejor escrita de esta manera:

>>> reduce(list.__add__, (list(mi) for mi in list_of_menuitems)) 

Esta es la sintaxis correcta para la comprensión de una lista anidada (brillante resumen dF!):

>>> [imagen para mi en list_of_menuitems para imagen in mi] 

Pero ninguno de estos métodos es tan eficiente como usar itertools.chain:

>>> ; de la cadena de importación de itertools >>> list(chain(*list_of_menuitems)) 

Y como señala @cdleary, probablemente sea mejor estilo evitar la magia del operador * usando chain.from_iterable así:

>>> cadena = itertools.chain.from_iterable([[1,2],[3],[5,89],[],[6]]) >>> imprimir(lista(cadena)) >>> [1, 2, 3, 5, 89, 6]