C'è un modo semplice per appiattire un elenco di iterabili con una comprensione dell'elenco o, in mancanza, quale considerereste il modo migliore per appiattire un elenco superficiale come questo, bilanciando prestazioni e leggibilità?
Ho provato ad appiattire un elenco del genere con una comprensione dell'elenco annidato, come questo:
[image for image in menuitem for menuitem in list_of_menuitems]
Ma ho problemi con la varietà NameError
lì, perché il nome "menuitem" non è definito
. Dopo aver cercato su Google e guardando in giro Stack Overflow, ho ottenuto i risultati desiderati con un'istruzione reduce
:
reduce(list.__add__, map(lambda x: list(x ), list_of_menuitems))
Ma questo metodo è abbastanza illeggibile perché ho bisogno che list(x)
chiami lì perché x è un Django QuerySet
oggetto.
Conclusione:
Grazie a tutti coloro che hanno contribuito a questa domanda. Ecco un riassunto di ciò che ho imparato. Lo sto anche trasformando in un wiki della comunità nel caso in cui altri vogliano aggiungere o correggere queste osservazioni.
La mia istruzione di riduzione originale è ridondante ed è meglio scrivere in questo modo:
>>> reduce(list.__add__, (list(mi) for mi in list_of_menuitems))
Questa è la sintassi corretta per la comprensione di un elenco annidato (riassunto brillante dF!):
>>> [immagine per mi in list_of_menuitems per immagine in mi]
Ma nessuno di questi metodi è efficiente quanto l'utilizzo di itertools.chain
:
>>> ; da itertools import chain >>> list(chain(*list_of_menuitems))
E come osserva @cdleary, probabilmente è meglio evitare * la magia dell'operatore usando chain.from_iterable
in questo modo:
>>> catena = itertools.chain.from_iterable([[1,2],[3],[5,89],[],[6]]) >>> print(elenco(catena)) >>> [1, 2, 3, 5, 89, 6]