`elif` en condicionales de comprensión de lista


129

¿Podemos usarlo elifen la comprensión de listas?

Ejemplo:

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

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

¿Podemos incluir la elifcomprensión en nuestra lista, de manera similar al código anterior?

Por ejemplo, una respuesta como:

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

Hasta ahora, solo he usado ify elseen comprensión de listas.

Respuestas:


250

Las expresiones condicionales de Python se diseñaron exactamente para este tipo de caso de 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']

Espero que esto ayude :-)


5
Hay una historia interesante en la sintaxis. Durante muchos años antes de su introducción, las "expresiones terciarias" fueron uno de los cinco cambios más solicitados en el idioma. Dado que Guido van Rossum lo diseñó explícitamente como un lenguaje basado en declaraciones, resistió firmemente durante mucho tiempo (las expresiones terciarias, y en particular su abuso, son fuentes de mucha oscuridad en el código). Cuando finalmente sucumbió, anunció que había elegido deliberadamente una sintaxis que desalienta el uso excesivo. No obstante, como de costumbre, hizo un elegante trabajo de diseño.
holdenweb

1
Ternario, maldita sea (escribió, notando su error disléxico demasiado tarde para editar).
holdenweb

2
Mientras voto a favor de esta respuesta, quiero mencionar esto: para 1 par de if / else es fácil de leer, 2 pares: se vuelve más difícil de entender. Ni siquiera menciones 3 pares. Si la expresión necesita 3 o más pares, un diccionario o una función separada facilitará la lectura y la comprensión.
Hai Vu

1
Me gustaría agregar no una solución para este problema, sino un recordatorio de código limpio: dado que esta lista de comprensión tiene tres condicionales, probablemente podría refactorizarse en un método más descriptivo. Mi punto es este: martinfowler.com/bliki/FunctionLength.html :)
Alvaro Cavalcanti

Me encontré con un caso en el que necesitaba un elif, pero solo dos valores. Usando este ejemplo, habría necesitado ['yes', 'no']estar hecho. Para ello, se puede hacer: ['yes' if v == 1 else 'no' for v in l if values in [1,2]]. Actualmente no puedo pensar en una forma más limpia de hacer esto.
dTanMan

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

4
Creo que esta forma es mucho más fácil de digerir que tratar de hacer una lógica if / else realmente larga y complicada dentro de la lista de
compilación

5
@jdi Aunque las expresiones condicionales pueden no ser de su agrado, fueron diseñadas específicamente para manejar cadenas if-elif-elif-else, tal como lo solicitó el OP. No son difíciles de aprender y pueden manejar con gracia las situaciones que no son tan susceptibles a la lógica de búsqueda de diccionario: 'A' if grade>=90 else 'B' if grade>=80 else 'C' if grade>=70 else 'F'.
Raymond Hettinger

1
¿Si hay alguna ventaja de definir dfuera de la comprensión?
Chris_Rands

La razón por la que me gusta más la comprensión de la lista es que se lee igual que en inglés. Incluso un no programador podría entender lo que hace. Con esta solución, debe comprender el método dict.get ().
Tim Skov Jacobsen

26

Puedes, más o menos.

Tenga en cuenta que cuando usa sytax como:

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

Está utilizando la forma ternaria del operador if / else (si está familiarizado con lenguajes como C, esto es como la ?:construcción :) (v == 1 ? 'yes' : 'no').

La forma ternaria del operador if / else no tiene un 'elif' incorporado, pero puede simularlo en la condición 'else':

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

Esto es como decir:

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

Por lo tanto, no hay una construcción 'elif' directa como la que preguntó, pero se puede simular con declaraciones if / else anidadas.


1
El código del último párrafo es muy revelador, ¡gracias!
devianceee

3

Tal vez quieras esto:

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

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

2

Puede utilizar la comprensión de listas si va a crear otra lista a partir del original.

>>> 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

Otra forma fácil es usar la comprensión de listas condicional como esta:

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

te da la respuesta correcta:

['sí', 'no', 'inactivo', 'inactivo', 'inactivo']

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.