2010-12-10 8 views
253

J'ai une liste l:si une autre dans la compréhension de la liste

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

Pour les numéros ci-dessus 45 inclusivement, je voudrais ajouter 1; et pour un nombre inférieur, il 5.

J'ai essayé

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

Mais il me donne une erreur de syntaxe. Comment puis-je atteindre un ifelse comme cela dans une liste de compréhension?

Répondre

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-chose si <condition>, sinon faire-quelque chose d'autre.

+2

Probablement utiliser une variable différente de 'x' comme condition dans l'explication en bas, puisque' x' est utilisé dans l'exemple non comme condition. – tscizzle

+0

qu'en est-il seulement d'inclure une variable dans la liste si une condition est remplie? l'autre serait juste passer? –

+3

il semble que le conditionnel peut aussi aller à la fin par exemple extraire des objets avec une condition spécifique (nom dans cet exemple) 'var_list = [v pour v dans tf.all_variables() si v.name == 'C: 0' ] ' –

78

Vous devez mettre l'expression au début de la compréhension de la liste, une instruction if à la fin des éléments de filtres!

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

+1 pour distinguer explicitement le rôle des conditionnels au début de la compréhension par rapport à la fin. Vous pouvez faire les deux en même temps, aussi; par exemple. '['upper' si item.isupper() else 'lower' pour item dans 'Omg! Crêpes!!!' if item.isalpha()] ' – Air

+0

Maintenant, je comprends la logique de commande. Merci à vous deux. – otocan

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

Et pour une récompense, voici le commentaire, je l'ai écrit à se rappeler ce la première fois que je l'ai fait cette erreur:

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

Très informatif! Cela rend les choses très claires, merci! :) – gideon

+0

@Dan D. Qu'en est-il de muliple 'if's? ie '[x + 1 si x> = 45 x-1 si x <10 sinon x + 5 pour x dans l]'? J'ai un genre similaire de [problème] (http://stackoverflow.com/questions/37582695/printing-certain-strings-different-colour-with-termcolor-colored) avec l'instruction if – 3kstc

+0

@ 3kstc: Pour cela: ' [x + 1 si x> = 45 sinon (x-1 si x <10 sinon x + 5) pour x dans l] '. Je vais regarder votre question. –

6

Vous pouvez déplacer le conditionnel à:

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

Mais ça commence à avoir l'air un peu moche, alors il vaudrait peut-être mieux utiliser une boucle normale. Notez que j'ai utilisé v au lieu de l pour la variable liste afin de réduire la confusion avec le numéro 1 (je pense que l et O devraient être évités en tant que noms de variables en toutes circonstances, même dans un exemple de code rapide).

173

La raison pour laquelle vous obtenez cette erreur est liée à la façon dont la compréhension de la liste est effectuée.

Gardez à l'esprit les éléments suivants:

[ expression for item in list if conditional ] 

équivaut à:

for item in list: 
    if conditional: 
     expression 

Lorsque le expression est dans un format légèrement différent (pensez commutation du sujet et de l'ordre du verbe dans une phrase).

Par conséquent, votre code [x+1 for x in l if x >= 45] fait ceci:

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

Cependant, ce code [x+1 if x >= 45 else x+5 for x in l] Est-ce que (après la réorganisation du expression):

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

Mon code ** user_albums = [{'albums': liens ['link']} pour les liens dans _details ['albums'] ['data'] si 'link' dans links.keys() else passe] ** getting erreur pour passer dans une autre condition – Shashank

+0

@shihon Pas besoin de 'else pass' dans une compréhension de liste; il est implicite que vous ne voulez pas que l'élément '{'albums': links ['link']}' soit inclus dans la liste lorsque la condition 'if 'link' dans links.keys()' est remplie. Format correct: 'user_albums = [{'albums': liens ['link']} pour les liens dans _details ['albums'] ['data'] si 'link' dans links.keys()]' – arboc7

+0

cela signifie, si les données n'existent pas ou nul il gère cette exception de sa propre personne? – Shashank

12

Vous pouvez également mettre l'expression conditionnelle entre parenthèses à l'intérieur la compréhension de la liste:

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

[false, true] [condition] est la syntaxe

6

Je viens d'avoir un problème similaire, et j'ai trouvé cette question et les réponses vraiment utiles.Voici la partie dont j'étais confus. Je l'écris explicitement parce que personne ne l'a dit en anglais:

L'itération va à la fin.

Normalement, une boucle va

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

Tout le monde déclare la partie de la compréhension de la liste simplement comme la première réponse a fait,

[ expression for item in list if conditional ] 

mais qui est en fait pas ce que vous faites dans ce cas. (Je tentais de le faire de cette façon)

Dans ce cas, il est plus comme ceci:

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

Comme dans [a if condition1 else b for i in list1 if condition2], les deux if s avec condition1 et condition2 font deux choses différentes. La partie (a if condition1 else b) est d'une expression lambda:

lambda x: a if condition1 else b 

tandis que l'autre condition2 est un autre lambda:

lambda x: condition2 

compréhension de la liste complète peut être considérer comme combinaison de map et filter:

map(lambda x: a if condition1 else b, filter(lambda x: condition2, list1)) 
Questions connexes