itertools.chain
itertools.chain
è la soluzione migliore per l'appiattimento di qualsiasi livello univoco nidificato - è altamente efficiente rispetto a qualsiasi soluzione di puro python.
Detto questo, funzionerà su tutti i valori iterabili, quindi è necessario un controllo se si desidera evitare di appiattire le stringhe, ad esempio.
Allo stesso modo, non si appiattisce magicamente su una profondità arbitraria. Detto questo, in genere, non è necessaria una soluzione così generica, ma è preferibile mantenere i dati strutturati in modo da non richiedere appiattimento in questo modo.
Edit: Direi che se si dovesse fare appiattimento arbitraria, questo è il modo migliore:
import collections
def flatten(iterable):
for el in iterable:
if isinstance(el, collections.Iterable) and not isinstance(el, str):
yield from flatten(el)
else:
yield el
ricordarsi di utilizzare basestring
in 2.x su str
e for subel in flatten(el): yield el
invece di yield from flatten(el)
pre-3.3 .
Come notato nei commenti, direi che questa è l'opzione nucleare, ed è probabile che causi più problemi di quanti ne risolva. Invece, l'idea migliore è di rendere il tuo output più regolare (l'output che contiene un elemento lo dia ancora come una tupla di un elemento, ad esempio) e fare un appiattimento regolare di un livello in cui viene introdotto, piuttosto che tutto alla fine.
Questo renderà più logico, leggibile e più facile da utilizzare con il codice. Naturalmente, ci sono casi in cui lo ha bisogno di per fare questo tipo di appiattimento (se i dati provengono da qualche parte con cui non si può incasinare, quindi non si ha altra scelta che prenderlo nel formato mal strutturato), in cui caso, questo tipo di soluzione potrebbe essere necessario, ma in generale, è probabilmente una cattiva idea.
Costruire una lista come questa è una soluzione davvero pessima, un generatore sarebbe molto più adatto. –
Direi che "soluzione veramente brutta" è un po 'forte. Se l'elenco annidato è relativamente piccolo, la creazione di un generatore potrebbe essere più lenta. Dipende dalla necessità Ho postato entrambi. – dawg
Potrebbe essere più lento creare un generatore su una piccola lista, ma quando è piccolo, la differenza di fuso orario non ha importanza. Quando è grande, tuttavia, potrebbe benissimo farlo. È preferibile utilizzare il generatore a prescindere, ed è più leggibile. Oltre a ciò, 'hasattr (e," __iter __ ")' è in genere un controllo eseguito meglio utilizzando l'ABC 'Iterable' - è più leggibile in questo modo. –