"elif" nei condizionali di comprensione delle liste


129

Possiamo usare elifnella comprensione delle liste?

Esempio :

l = [1, 2, 3, 4, 5]

for values in l:
    if values==1:
        print 'yes'
    elif values==2:
        print 'no'
    else:
        print 'idle'

Possiamo includere elifnella nostra lista di comprensione, in modo simile al codice sopra?

Ad esempio, una risposta come:

['yes', 'no', 'idle', 'idle', 'idle']

Fino ad ora, ho utilizzato solo ife elsenella comprensione delle liste.

Risposte:


250

Le espressioni condizionali di Python sono state progettate esattamente per questo tipo di caso d'uso:

>>> l = [1, 2, 3, 4, 5]
>>> ['yes' if v == 1 else 'no' if v == 2 else 'idle' for v in l]
['yes', 'no', 'idle', 'idle', 'idle']

Spero che questo ti aiuti :-)


5
C'è una storia interessante nella sintassi. Per molti anni prima della loro introduzione le "espressioni terziarie" sono state uno dei cinque cambiamenti più richiesti nella lingua. Poiché Guido van Rossum lo ha progettato esplicitamente come un linguaggio basato su affermazioni, ha resistito fermamente a lungo (le espressioni terziarie, e in particolare il loro abuso, sono fonte di molta oscurità nel codice). Quando alla fine cedette, annunciò di aver scelto deliberatamente una sintassi che scoraggiava l'uso eccessivo. Come al solito, ha svolto comunque un elegante lavoro di design.
holdenweb

1
Ternario, dannazione (scrisse, notando il suo errore dislessico troppo tardi per essere modificato).
holdenweb

2
Mentre voto questa risposta, voglio menzionare questo: per 1 paio di if / else è facile da leggere, 2 paia: sta diventando più difficile da capire. Non menzionare nemmeno 3 paia. Se l'espressione necessita di 3 o più coppie, un dizionario o una funzione separata renderà le cose più facili da leggere e comprendere.
Hai Vu

1
Vorrei aggiungere non una soluzione per questo problema, ma un promemoria del codice pulito: poiché questa comprensione della lista ha tre condizionali, probabilmente potrebbe essere riformattata in un metodo più descrittivo. Il punto è questo: martinfowler.com/bliki/FunctionLength.html :)
Alvaro Cavalcanti

Mi sono imbattuto in un caso in cui avevo bisogno di un elif, ma solo due valori. Usando questo esempio, avrei avuto bisogno solo ['yes', 'no']di essere creato. Per fare questo, si può fare: ['yes' if v == 1 else 'no' for v in l if values in [1,2]]. Al momento non riesco a pensare a un modo più pulito per farlo.
dTanMan

48
>>> d = {1: 'yes', 2: 'no'}
>>> [d.get(x, 'idle') for x in l]
['yes', 'no', 'idle', 'idle', 'idle']

4
Penso che questo modulo sia molto più facile da digerire che provare a fare una logica if / else davvero lunga e complicata all'interno della lista comp
jdi

5
@jdi Sebbene le espressioni condizionali possano non essere di tuo gusto, sono state progettate specificamente per gestire le catene if-elif-elif-else, proprio come richiesto dall'OP. Essi non sono difficili da imparare e in grado di gestire con garbo le situazioni che non sono così suscettibili di logica consultazione dei dizionari: 'A' if grade>=90 else 'B' if grade>=80 else 'C' if grade>=70 else 'F'.
Raymond Hettinger

1
Se c'è un vantaggio nel definire dal di fuori della comprensione?
Chris_Rands

Il motivo per cui mi piace di più la comprensione della lista è che si legge proprio come l'inglese. Anche un non programmatore sarebbe in grado di capire cosa fa. Con questa soluzione devi capire il metodo dict.get ().
Tim Skov Jacobsen

26

Puoi, più o meno.

Nota che quando usi sytax come:

['yes' if v == 1 else 'no' for v in l]

Stai usando la forma ternaria dell'operatore if / else (se hai familiarità con linguaggi come il C, questo è come il ?:costrutto :) (v == 1 ? 'yes' : 'no').

La forma ternaria dell'operatore if / else non ha un 'elif' integrato, ma puoi simularlo nella condizione 'else':

['yes' if v == 1 else 'no' if v == 2 else 'idle' for v in l]

È come dire:

for v in l:
    if v == 1 :
        print 'yes'
    else:
        if v == 2:
            print 'no'
        else:
            print 'idle'

Quindi non esiste un costrutto "elif" diretto come richiesto, ma può essere simulato con istruzioni if ​​/ else annidate.


1
L'ultimo codice di paragrafo è molto perspicace, grazie!
devianceee

3

Forse vuoi questo:

l = [1, 2, 3, 4, 5] 

print ([['idle','no','yes'][2*(n==1)+(n==2)] for n in l])

2

Puoi usare la comprensione dell'elenco se creerai un altro elenco dall'originale.

>>> l = [1, 2, 3, 4, 5]
>>> result_map = {1: 'yes', 2: 'no'}
>>> [result_map[x] if x in result_map else 'idle' for x in l]
['yes', 'no', 'idle', 'idle', 'idle']

2

Un altro modo semplice è usare la comprensione dell'elenco condizionale in questo modo:

l=[1,2,3,4,5]
print [[["no","yes"][v==1],"idle"][v!=1 and v!=2] for v in l]

ti dà la risposta corretta:

["sì", "no", "idle", "idle", "idle"]

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.