Comprensione elenco di una riga: varianti if-else


178

Riguarda maggiormente la sintassi della comprensione dell'elenco di Python. Ho una comprensione dell'elenco che produce un elenco di numeri dispari di un determinato intervallo:

[x for x in range(1, 10) if x % 2]

Questo crea un filtro: ho un elenco di sorgenti, in cui rimuovo i numeri pari ( if x % 2). Vorrei usare qualcosa come if-then-else qui. Il codice seguente non riesce:

>>> [x for x in range(1, 10) if x % 2 else x * 100]
  File "<stdin>", line 1
    [x for x in range(1, 10) if x % 2 else x * 100]
                                         ^
SyntaxError: invalid syntax

Esiste un'espressione python come if-else:

1 if 0 is 0 else 3

Come usarlo all'interno di una lista di comprensione?


1
Fow quanto vale, hai una "comprensione della lista", non un generatore. La sintassi finale è la stessa tranne che i generatori usano al ()posto di [].
mgilson,


2
Mi ci è voluto un po 'per capire perché if x % 2 elimina i numeri pari (invece di tenerli) - è perché quando xsi verifica anche l' x % 2espressione 0, che, a sua volta, valuta False, mentre qualsiasi inttranne si 0valuta True.

Risposte:


328

x if y else zè la sintassi per l'espressione che stai restituendo per ciascun elemento. Quindi hai bisogno di:

[ x if x%2 else x*100 for x in range(1, 10) ]

La confusione deriva dal fatto che stai usando un filtro nel primo esempio, ma non nel secondo. Nel secondo esempio stai solo mappando ciascun valore su un altro, usando un'espressione di operatore ternario.

Con un filtro, è necessario:

[ EXP for x in seq if COND ]

Senza filtro è necessario:

[ EXP for x in seq ]

e nel tuo secondo esempio, l'espressione è "complessa", che coinvolge un if-else.


2
Ho una domanda ... [x for x in range(1, 10) if x % 2]è la sintassi corretta. [x if x % 2 for x in range(1, 10)]- questa non è, ma [x if x%2 else x*100 for x in range(1, 10)]è di nuovo, sintassi corretta. Come mai?
Ducin,

@tkoomzaaskz nel tuo secondo esempio, questo non è né un operatore ternario-if-else (manca il else), né un filtro (poiché è da EXPparte della comprensione dell'elenco)
shx2

3
@tkoomzaaskz Per chiarire ulteriormente, si noti che è possibile aggiungere un secondo ifalla fine: [x if x%2 else x*100 for x in range(1, 10) if not x%3]il primo iffa parte dell'operatore ternario, il secondo iffa parte della sintassi di comprensione dell'elenco. Il tutto x if x%2 else x*100è "allo stesso livello" di un semplice 2*x, è l'espressione da valutare sul lato sinistro del for, quando il filtraggio di if not x%3è già avvenuto.
zx81

Ciao, un'istruzione di una riga sarebbe più performante che farla su due righe come for i in x:e poi nel ciclo for if i == y:?
Alexis.Rolland,

23
[x if x % 2 else x * 100 for x in range(1, 10) ]

12

Puoi farlo anche con la comprensione dell'elenco:

A=[[x*100, x][x % 2 != 0] for x in range(1,11)]
print A

1
Molto bella. Una fetta booleana. Grazie, mi hai appena dato una soluzione più facile da leggere.

Puoi anche raddoppiare i compiti in questo modo: A, B = [10,11] [a == 19], [1,14] [a == 20]
Stefan Gruenwald

10

Solo un'altra soluzione, spero che qualcuno possa piacere:

Utilizzo: [Falso, Vero] [Espressione]

>>> map(lambda x: [x*100, x][x % 2 != 0], range(1,10))
[1, 200, 3, 400, 5, 600, 7, 800, 9]
>>>

3

Sono stato in grado di farlo

>>> [x if x % 2 != 0 else x * 100 for x in range(1,10)]
    [1, 200, 3, 400, 5, 600, 7, 800, 9]
>>>
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.