Comprensione dell'elenco in un elenco nidificato?


220

Ho questo elenco nidificato:

l = [['40', '20', '10', '30'], ['20', '20', '20', '20', '20', '30', '20'], ['30', '20', '30', '50', '10', '30', '20', '20', '20'], ['100', '100'], ['100', '100', '100', '100', '100'], ['100', '100', '100', '100']]

Ora, quello che voglio fare è convertire ogni elemento in un elenco in float. La mia soluzione è questa:

newList = []
for x in l:
  for y in x:
    newList.append(float(y))

Ma questo può essere fatto usando la comprensione dell'elenco nidificato, giusto?

quello che ho fatto è:

[float(y) for y in x for x in l]

Ma poi il risultato è un mucchio di 100 con la somma di 2400.

qualsiasi soluzione, una spiegazione sarebbe molto apprezzata. Grazie!


15
Vuoi anche appiattire la tua lista?
Greg Hewgill,

@GregHewgill: OP non ha risposto, ma in base alla risposta che ha accettato, sembra che volesse mantenere l'annidamento così com'è.
smci,

Risposte:


319

Ecco come lo faresti con una comprensione dell'elenco nidificato:

[[float(y) for y in x] for x in l]

Questo ti darebbe un elenco di elenchi, simile a quello con cui hai iniziato, tranne con float anziché stringhe. Se si desidera un elenco semplice, si utilizzerà [float(y) for x in l for y in x].


192

Ecco come convertire il ciclo nidificato per la comprensione dell'elenco nidificato:

inserisci qui la descrizione dell'immagine

Ecco come funziona la comprensione dell'elenco nidificato:

            l a b c d e f
                  
In [1]: l = [ [ [ [ [ [ 1 ] ] ] ] ] ]
In [2]: for a in l:
   ...:     for b in a:
   ...:         for c in b:
   ...:             for d in c:
   ...:                 for e in d:
   ...:                     for f in e:
   ...:                         print(float(f))
   ...:                         
1.0

In [3]: [float(f)
         for a in l
   ...:     for b in a
   ...:         for c in b
   ...:             for d in c
   ...:                 for e in d
   ...:                     for f in e]
Out[3]: [1.0]

Nel tuo caso, sarà qualcosa del genere.

In [4]: new_list = [float(y) for x in l for y in x]

21
Super utile! Indica chiaramente che i loop (dall'alto verso il basso) sono ordinati da sinistra a destra nel generatore. Questo non è ovvio poiché in alcuni (f(x) for x in l)punti la seconda riga dell'equivalente for-loop a sinistra.
user48956

Questa sembra essere l'unica spiegazione che sta colpendo a casa con me, grazie!
Douglas Plumley,

49
>>> l = [['40', '20', '10', '30'], ['20', '20', '20', '20', '20', '30', '20'], ['30', '20', '30', '50', '10', '30', '20', '20', '20'], ['100', '100'], ['100', '100', '100', '100', '100'], ['100', '100', '100', '100']]
>>> new_list = [float(x) for xs in l for x in xs]
>>> new_list
[40.0, 20.0, 10.0, 30.0, 20.0, 20.0, 20.0, 20.0, 20.0, 30.0, 20.0, 30.0, 20.0, 30.0, 50.0, 10.0, 30.0, 20.0, 20.0, 20.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0]

42

Non sei sicuro di quale sia l'output desiderato, ma se stai utilizzando la comprensione dell'elenco, l'ordine segue l'ordine dei loop nidificati, che hai al contrario. Quindi ho ottenuto quello che penso tu voglia con:

[float(y) for x in l for y in x]

Il principio è: usa lo stesso ordine che avresti usato per scriverlo come nidificato per i loop.


questa dovrebbe essere la risposta, come a volte non ci vuole parentesi quadra l'iteratool
zincatura

1
questa potrebbe non essere la risposta corretta in quanto genera un elenco non nidificato, ma è quello che stavo cercando, specialmente il principio . Grazie!
Rodrigo E. Principe,

4

Ho avuto un problema simile da risolvere, quindi mi sono imbattuto in questa domanda. Ho fatto un confronto delle prestazioni della risposta di Andrew Clark e Narayan che vorrei condividere.

La differenza principale tra due risposte è il modo in cui ripetono gli elenchi interni. Uno di essi utilizza la mappa integrata, mentre l'altro utilizza la comprensione dell'elenco. La funzione Mappa ha un leggero vantaggio in termini di prestazioni rispetto alla sua equivalente comprensione dell'elenco se non richiede l'uso di lambda . Quindi, nel contesto di questa domanda, mapdovrebbe funzionare leggermente meglio della comprensione dell'elenco.

Facciamo un benchmark delle prestazioni per vedere se è effettivamente vero. Ho usato Python versione 3.5.0 per eseguire tutti questi test. Nella prima serie di test, vorrei mantenere gli elementi per lista da 10 e variare il numero di liste da 10 a 100.000

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,10))]*10]"
>>> 100000 loops, best of 3: 15.2 usec per loop   
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,10))]*10]"
>>> 10000 loops, best of 3: 19.6 usec per loop 

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,10))]*100]"
>>> 100000 loops, best of 3: 15.2 usec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,10))]*100]"
>>> 10000 loops, best of 3: 19.6 usec per loop 

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,10))]*1000]"
>>> 1000 loops, best of 3: 1.43 msec per loop   
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,10))]*1000]"
>>> 100 loops, best of 3: 1.91 msec per loop

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,10))]*10000]"
>>> 100 loops, best of 3: 13.6 msec per loop   
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,10))]*10000]"
>>> 10 loops, best of 3: 19.1 msec per loop

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,10))]*100000]"
>>> 10 loops, best of 3: 164 msec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,10))]*100000]"
>>> 10 loops, best of 3: 216 msec per loop

inserisci qui la descrizione dell'immagine

Nella prossima serie di test vorrei aumentare il numero di elementi per elenchi a 100 .

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,100))]*10]"
>>> 10000 loops, best of 3: 110 usec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,100))]*10]"
>>> 10000 loops, best of 3: 151 usec per loop

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,100))]*100]"
>>> 1000 loops, best of 3: 1.11 msec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,100))]*100]"
>>> 1000 loops, best of 3: 1.5 msec per loop

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,100))]*1000]"
>>> 100 loops, best of 3: 11.2 msec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,100))]*1000]"
>>> 100 loops, best of 3: 16.7 msec per loop

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,100))]*10000]"
>>> 10 loops, best of 3: 134 msec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,100))]*10000]"
>>> 10 loops, best of 3: 171 msec per loop

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,100))]*100000]"
>>> 10 loops, best of 3: 1.32 sec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,100))]*100000]"
>>> 10 loops, best of 3: 1.7 sec per loop

inserisci qui la descrizione dell'immagine

Facciamo un passo coraggioso e modificiamo il numero di elementi negli elenchi in 1000

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,1000))]*10]"
>>> 1000 loops, best of 3: 800 usec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,1000))]*10]"
>>> 1000 loops, best of 3: 1.16 msec per loop

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,1000))]*100]"
>>> 100 loops, best of 3: 8.26 msec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,1000))]*100]"
>>> 100 loops, best of 3: 11.7 msec per loop

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,1000))]*1000]"
>>> 10 loops, best of 3: 83.8 msec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,1000))]*1000]"
>>> 10 loops, best of 3: 118 msec per loop

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,1000))]*10000]"
>>> 10 loops, best of 3: 868 msec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,1000))]*10000]"
>>> 10 loops, best of 3: 1.23 sec per loop

>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,1000))]*100000]"
>>> 10 loops, best of 3: 9.2 sec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,1000))]*100000]"
>>> 10 loops, best of 3: 12.7 sec per loop

inserisci qui la descrizione dell'immagine

Da questi test possiamo concludere che map in questo caso ha un vantaggio in termini di prestazioni rispetto alla comprensione dell'elenco. Questo è applicabile anche se stai provando a trasmettere a into str. Per un numero limitato di elenchi con meno elementi per elenco, la differenza è trascurabile. Per elenchi più grandi con più elementi per elenco, uno potrebbe preferire mapinvece della comprensione dell'elenco, ma dipende totalmente dalle esigenze dell'applicazione.

Tuttavia trovo personalmente che la comprensione dell'elenco sia più leggibile e idiomatica di map. È uno standard di fatto in Python. Di solito le persone sono più competenti e più a proprio agio (specialmente i principianti) nell'usare la comprensione dell'elenco rispetto a map.


4

Dato che sono un po 'in ritardo qui, ma ho voluto condividere il modo in cui la comprensione dell'elenco funziona in particolare la comprensione dell'elenco nidificato:

New_list= [[float(y) for x in l]

è in realtà lo stesso di:

New_list=[]
for x in l:
    New_list.append(x)

E ora la comprensione dell'elenco nidificato:

[[float(y) for y in x] for x in l]

è uguale a;

new_list=[]
for x in l:
    sub_list=[]
    for y in x:
        sub_list.append(float(y))

    new_list.append(sub_list)

print(new_list)

produzione:

[[40.0, 20.0, 10.0, 30.0], [20.0, 20.0, 20.0, 20.0, 20.0, 30.0, 20.0], [30.0, 20.0, 30.0, 50.0, 10.0, 30.0, 20.0, 20.0, 20.0], [100.0, 100.0], [100.0, 100.0, 100.0, 100.0, 100.0], [100.0, 100.0, 100.0, 100.0]]

3

Se non ti piacciono le comprensione dell'elenco nidificato, puoi utilizzare anche la funzione mappa ,

>>> from pprint import pprint

>>> l = l = [['40', '20', '10', '30'], ['20', '20', '20', '20', '20', '30', '20'], ['30', '20', '30', '50', '10', '30', '20', '20', '20'], ['100', '100'], ['100', '100', '100', '100', '100'], ['100', '100', '100', '100']] 

>>> pprint(l)
[['40', '20', '10', '30'],
['20', '20', '20', '20', '20', '30', '20'],
['30', '20', '30', '50', '10', '30', '20', '20', '20'],
['100', '100'],
['100', '100', '100', '100', '100'],
['100', '100', '100', '100']]

>>> float_l = [map(float, nested_list) for nested_list in l]

>>> pprint(float_l)
[[40.0, 20.0, 10.0, 30.0],
[20.0, 20.0, 20.0, 20.0, 20.0, 30.0, 20.0],
[30.0, 20.0, 30.0, 50.0, 10.0, 30.0, 20.0, 20.0, 20.0],
[100.0, 100.0],
[100.0, 100.0, 100.0, 100.0, 100.0],
[100.0, 100.0, 100.0, 100.0]]

Il tuo codice genera oggetti mappa anziché elenchi: >>> float_l = [map(float, nested_list) for nested_list in l] [[<map at 0x47be9b0>], [<map at 0x47be2e8>], [<map at 0x47be4a8>], [<map at 0x47beeb8>], [<map at 0x484b048>], [<map at 0x484b0b8>]] ma aggiungendo una chiamata aggiuntiva all'elenco funziona come previsto: >>> float_l = [list(map(float, nested_list)) for nested_list in l]
pixelperfect

@pixelperfect dovuto alla modifica ( male informata ..) python3per restituire i generatori fuori comprensione.
javadba,

2

Sì, puoi farlo con un tale codice:

l = [[float(y) for y in x] for x in l]

[float(y) for y in x for x in l]questo porterebbe a un mucchio di 100 con una somma di 2400.
Boy Pasmo

2

Questo problema può essere risolto senza l'uso di loop. Il codice di riga singola sarà sufficiente per questo. Anche l'utilizzo di Nested Map con la funzione lambda funzionerà qui.

l = [['40', '20', '10', '30'], ['20', '20', '20', '20', '20', '30', '20'], ['30', '20', '30', '50', '10', '30', '20', '20', '20'], ['100', '100'], ['100', '100', '100', '100', '100'], ['100', '100', '100', '100']]

map(lambda x:map(lambda y:float(y),x),l)

E l'elenco di output sarebbe il seguente:

[[40.0, 20.0, 10.0, 30.0], [20.0, 20.0, 20.0, 20.0, 20.0, 30.0, 20.0], [30.0, 20.0, 30.0, 50.0, 10.0, 30.0, 20.0, 20.0, 20.0], [100.0, 100.0], [100.0, 100.0, 100.0, 100.0, 100.0], [100.0, 100.0, 100.0, 100.0]]

1
Lambdas ha qualche vantaggio in termini di prestazioni rispetto alle soluzioni di @Andrew Clark o Harry Binswanger (la comprensione della lista più vanigliata)? Come lambda sembrano più difficili da leggere.
StefanJCollier,

0

Il modo migliore per farlo secondo me è usare il itertoolspacchetto di python .

>>>import itertools
>>>l1 = [1,2,3]
>>>l2 = [10,20,30]
>>>[l*2 for l in itertools.chain(*[l1,l2])]
[2, 4, 6, 20, 40, 60]


-2
    deck = [] 
    for rank in ranks:
        for suit in suits:
            deck.append(('%s%s')%(rank, suit))

Ciò può essere ottenuto utilizzando la comprensione dell'elenco:

[deck.append((rank,suit)) for suit in suits for rank in ranks ]

1
Ciò non sembra affatto rispondere alla domanda. Si noti che tutto ciò che è stato pubblicato come risposta deve essere un tentativo di rispondere alla domanda a cui è pubblicato.
Baum mit Augen

Sebbene questo frammento di codice possa risolvere la domanda, inclusa una spiegazione aiuta davvero a migliorare la qualità del tuo post. Ricorda che stai rispondendo alla domanda per i lettori in futuro e che queste persone potrebbero non conoscere i motivi del tuo suggerimento sul codice. Cerca anche di non aggiungere il tuo codice a commenti esplicativi, ciò riduce la leggibilità sia del codice che delle spiegazioni!
Filnor,

Annidato per loop usando la comprensione dell'elenco,
ADITYA KUMAR

1
Ok, a quanto pare, questo è un tentativo di rispondere alla domanda. Tuttavia, questo sembra riguardare uno scenario completamente diverso rispetto a OP, non si tratta nemmeno di elenchi nidificati come input e anche se si modifica il suggerimento è praticamente ciò che OP ha già provato. Inoltre, non vedo come un esempio di carte sia di aiuto quando la domanda riguarda la conversione di stringhe in float.
Baum mit Augen
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.