`elif` dans les conditions de compréhension de liste

129

Pouvons-nous utiliser elifdans la compréhension de liste?

Exemple :

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

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

Pouvons-nous inclure la elifcompréhension de la liste dans notre liste, d'une manière similaire au code ci-dessus?

Par exemple, une réponse comme:

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

Jusqu'à présent, je n'ai utilisé ifet elseen compréhension de liste.

soi
la source

Réponses:

250

Les expressions conditionnelles de Python ont été conçues exactement pour ce type de cas d'utilisation:

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

J'espère que cela t'aides :-)

Raymond Hettinger
la source
5
Il y a une histoire intéressante dans la syntaxe. Pendant de nombreuses années avant leur introduction, les "expressions tertiaires" ont été l'un des cinq changements les plus demandés dans la langue. Puisque Guido van Rossum l'a explicitement conçu comme un langage basé sur des déclarations, il a fermement résisté pendant longtemps (les expressions tertiaires, et en particulier leur abus, sont des sources de beaucoup d'obscurité dans le code). Lorsqu'il a finalement succombé, il a annoncé qu'il avait délibérément choisi une syntaxe qui décourageait la surutilisation. Comme d'habitude, il a néanmoins fait un travail de design élégant.
holdenweb
1
Ternaire, bon sang (il écrivit, remarquant son erreur dyslexique trop tard pour être édité).
holdenweb
2
Pendant que je vote pour cette réponse, je tiens à mentionner ceci: pour 1 paire de if / else est facile à lire, 2 paires: c'est de plus en plus difficile à comprendre. Ne mentionnez même pas 3 paires. Si l'expression nécessite 3 paires ou plus, un dictionnaire ou une fonction distincte rendra les choses plus faciles à lire et à comprendre.
Hai Vu le
1
Je voudrais ajouter non pas une solution à ce problème, mais un rappel de code propre: puisque cette compréhension de liste a trois conditions, elle pourrait probablement être refactorisée en une méthode plus descriptive. Mon point est le suivant: martinfowler.com/bliki/FunctionLength.html :)
Alvaro Cavalcanti
Je suis tombé sur un cas où j'avais besoin d'un elif, mais seulement deux valeurs. En utilisant cet exemple, j'aurais juste eu besoin ['yes', 'no']d'être fait. Pour ce faire, vous pouvez faire: ['yes' if v == 1 else 'no' for v in l if values in [1,2]]. Je ne peux actuellement pas penser à un moyen plus propre de le faire.
dTanMan
48
>>> d = {1: 'yes', 2: 'no'}
>>> [d.get(x, 'idle') for x in l]
['yes', 'no', 'idle', 'idle', 'idle']
Ignacio Vazquez-Abrams
la source
4
Je pense que ce formulaire est beaucoup plus facile à digérer que d'essayer de faire une logique if / else vraiment longue et compliquée dans la liste comp
jdi
5
@jdi Bien que les expressions conditionnelles ne soient pas à votre goût, elles ont été spécifiquement conçues pour gérer les chaînes if-elif-elif-else, tout comme l'OP l'a demandé. Ils ne sont pas difficiles à apprendre et peut gérer grâce des situations qui ne sont pas aussi prête à la logique de recherche dans le dictionnaire: 'A' if grade>=90 else 'B' if grade>=80 else 'C' if grade>=70 else 'F'.
Raymond Hettinger
1
Y a-t-il un avantage à définir en ddehors de la compréhension?
Chris_Rands
La raison pour laquelle j'aime mieux la compréhension de la liste est qu'elle se lit comme l'anglais. Même un non-programmeur pourrait comprendre ce qu'il fait. Avec cette solution, vous devez comprendre la méthode dict.get ().
Tim Skov Jacobsen
26

Vous pouvez, en quelque sorte.

Notez que lorsque vous utilisez une syntaxe comme:

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

Vous utilisez la forme ternaire de l'opérateur if / else (si vous êtes familier avec des langages comme C, c'est comme la ?:construction:) (v == 1 ? 'yes' : 'no').

La forme ternaire de l'opérateur if / else n'a pas de 'elif' intégré, mais vous pouvez le simuler dans la condition 'else':

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

C'est comme dire:

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

Il n'y a donc pas de construction 'elif' directe comme vous l'avez demandé, mais elle peut être simulée avec des instructions if / else imbriquées.

mathématique.café
la source
1
Le dernier code de paragraphe est très perspicace merci!
devianceee
3

Peut-être que vous voulez ceci:

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

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

Vous pouvez utiliser la compréhension de liste si vous allez créer une autre liste à partir de l'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']
San4ez
la source
2

Un autre moyen simple consiste à utiliser la compréhension de liste conditionnelle comme ceci:

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

vous donne la bonne réponse:

['oui', 'non', 'inactif', 'inactif', 'inactif']

Stefan Gruenwald
la source