2010-12-10 14 views
253

Tengo una lista l:si bien en una lista por comprensión

l = [22, 13, 45, 50, 98, 69, 43, 44, 1] 

Para los números superiores a 45 inclusive, me gustaría añadir al menos 1; y para los números menos de lo que, 5.

Probé

[x+1 for x in l if x >= 45 else x+5] 

pero me da un error de sintaxis. ¿Cómo puedo lograr un ifelse como este en una lista de comprensión?

Respuesta

309
>>> l = [22, 13, 45, 50, 98, 69, 43, 44, 1] 
>>> [x+1 if x >= 45 else x+5 for x in l] 
[27, 18, 46, 51, 99, 70, 48, 49, 6] 

Do-algo si <condition>, de lo contrario hacer alguna otra cosa.

+2

Probablemente debería usar una variable diferente a 'x' como la condición en la explicación en la parte inferior, ya que' x' se usa en el ejemplo no como la condición. – tscizzle

+0

¿qué pasa si solo se incluye una variable en la lista si se cumple una condición? ¿el otro solo pasaría? –

+3

parece que el condicional también puede ir al final, por ejemplo, extraer objetos con una condición específica (nombre en este ejemplo) 'var_list = [v para v en tf.all_variables() si v.name == 'C: 0' ] ' –

78

Debe poner la expresión al comienzo de la lista de comprensión, una instrucción if al final filtra elementos!

[x+1 if x >= 45 else x+5 for x in l] 
+17

+1 para distinguir explícitamente el papel de los condicionales al comienzo de la comprensión vs. al final. Puedes hacer ambas cosas al mismo tiempo, también; p.ej. '['upper' if item.isupper() else 'inferior' para el elemento en 'Omg! ¡¡¡panqueques!!!' if item.isalpha()] ' – Air

+0

AHORA entiendo la lógica de ordenamiento. Gracias a los dos. – otocan

104
[x+1 if x >= 45 else x+5 for x in l] 

Y para una recompensa, aquí está el comentario, he escrito para recordar la primera vez que hice este error:

Python's conditional expression is a if C else b and can't be used as:

[a for i in items if C else b] 

The right form is:

[a if C else b for i in items] 

Even though there is a valid form:

[a for i in items if C] 

But that isn't the same as that is how you filter by C , but they can be combined:

[a if tC else b for i in items if fC] 
+0

¡Muy informativo! Esto deja las cosas muy claras, ¡gracias! :) – gideon

+0

@Dan D. ¿Qué hay de 'si' s? es decir '' x + 1 si x> = 45 x-1 si x <10 else x + 5 para x en l] '? Tengo un tipo similar de [problema] (http://stackoverflow.com/questions/37582695/printing-certain-strings-different-colour-with-termcolor-colored) con la instrucción if – 3kstc

+0

@ 3kstc: Para eso: ' [x + 1 si x> = 45 else (x-1 si x <10 else x + 5) para x en l] '. Veré tu pregunta. –

6

Se podía mover el condicional a:

v = [22, 13, 45, 50, 98, 69, 43, 44, 1] 
[ (x+1 if x >=45 else x+5) for x in v ] 

Pero está empezando a verse un poco feo, por lo que es mejor que uses un ciclo normal. Tenga en cuenta que utilicé v en lugar de l para la variable de la lista para reducir la confusión con el número 1 (creo que l y O deben evitarse como nombres de variables bajo ninguna circunstancia, incluso en el código de ejemplo rápido y sucio).

173

La razón por la que recibe este error tiene que ver con la forma en que se realiza la comprensión de la lista.

Tenga en cuenta lo siguiente:

[ expression for item in list if conditional ] 

es equivalente a:

for item in list: 
    if conditional: 
     expression 

Cuando el expression está en un formato ligeramente diferente (piensa cambiar el tema y el orden verbo en una oración).

Por lo tanto, su código [x+1 for x in l if x >= 45] hace esto:

for x in l: 
    if x >= 45: 
     x+1 

Sin embargo, este código [x+1 if x >= 45 else x+5 for x in l] hace esto (después de la reordenación de la expression):

for x in l: 
    if x>=45: x+1 
    else: x+5 
+1

Mi código ** user_albums = [{'albums': links ['link']} para enlaces en _details ['albums'] ['data'] si 'link' en links.keys() else pass] ** getting error para pasar en otra condición – Shashank

+0

@shihon No hay necesidad de 'else pass' en una lista de comprensión; está implícito que no desea que el elemento '{'albums': links ['link']}' se incluya en la lista cuando se cumple la condición 'if 'link' en links.keys()'. Formato correcto: 'user_albums = [{'albums': links ['link']} para enlaces en _details ['albums'] ['data'] si 'link' en links.keys()]' – arboc7

+0

eso significa, si datos no existen o nulo manejar esta excepción desde su propio ?? – Shashank

12

También se puede poner la expresión condicional entre corchetes en el interior la lista de comprensión:

l = [22, 13, 45, 50, 98, 69, 43, 44, 1] 
    print [[x+5,x+1][x >= 45] for x in l] 

[falso, cierto] [condición] es la sintaxis

6

Acabo de tener un problema similar, y encontré esta pregunta y las respuestas realmente útiles.Aquí está la parte que me confundió. Lo estoy escribiendo explícitamente porque nadie lo declaró simplemente en inglés:

La iteración va al final.

Normalmente, un bucle va

for this many times: 
    if conditional: 
     do this thing 
    else: 
     do something else 

Todo el mundo afirma la parte lista por comprensión simplemente como la primera respuesta hizo,

[ expression for item in list if conditional ] 

pero eso no es realmente lo que se hace en este caso. (Yo estaba tratando de hacerlo de esa manera)

En este caso, es de la misma familia:

[ expression if conditional else other thing for this many times ] 
5

Al igual que en [a if condition1 else b for i in list1 if condition2], los dos if s con condition1 y condition2 haciendo dos cosas diferentes. La parte (a if condition1 else b) es de una expresión lambda:

lambda x: a if condition1 else b 

mientras que el otro condition2 es otro lambda:

lambda x: condition2 

Whole lista por comprensión puede ser sentido como combinación de map y filter:

map(lambda x: a if condition1 else b, filter(lambda x: condition2, list1)) 
Cuestiones relacionadas