Achatando uma lista superficial em Python

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

Existe uma maneira simples de nivelar uma lista de iteráveis com uma compreensão de lista ou, na falta disso, qual você consideraria a melhor maneira de nivelar uma lista superficial como essa, equilibrando desempenho e legibilidade?

Tentei nivelar essa lista com uma compreensão de lista aninhada, assim:

[image for image in menuitem for menuitem in list_of_menuitems] 

Mas tenho problemas com a variedade NameError, porque o name "menuitem" não está definido. Depois de pesquisar e pesquisar no Stack Overflow, obtive os resultados desejados com uma instrução reduce:

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

Mas este método é bastante ilegível porque eu preciso que list(x) chame lá porque x é um Django QuerySet objeto.

Conclusão:

Obrigado a todos que contribuíram para esta pergunta. Aqui está um resumo do que aprendi. Também estou tornando este um wiki da comunidade caso outros queiram adicionar ou corrigir essas observações.

Minha declaração de redução original é redundante e está melhor escrita desta forma:

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

Esta é a sintaxe correta para uma compreensão de lista aninhada (Resumo brilhante dF!):

>>> [image for mi in list_of_menuitems for image in mi] 

Mas nenhum desses métodos é tão eficiente quanto usar itertools.chain:

>>> ; da cadeia de importação itertools >>> list(chain(*list_of_menuitems)) 

E como @cdleary observa, provavelmente é melhor evitar a mágica do operador * usando chain.from_iterable assim:

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