1
votes

la compréhension de la liste ne s’évalue pas comme prévu

J'ai la liste suivante:

[7, 9, 7, 15, None, 2, 0]

.. et je voulais une compréhension de liste qui renverra l'entier dans l'élément s'il y en a un même s'il vaut 0 et et qui renverra 1 pour un élément où les deux sous-éléments sont Aucun.

Je l'ai amené aussi loin que ceci:

[a or b if (a!=0 and b!=0) else 0 if set([a,b])=={0,None} else 1 if set([a,b])=={None} else -10 for a,b in z]

.. qui fonctionne presque , il renvoie:

z = [
[7,None], 
[9,None], 
[None,7], 
[None, 15], 
[None, None], 
[2,None], 
[0,None]]

Il n'a donc pas réussi à transformer l'élément [None, None] en 1. Quelqu'un sait-il comment le réparer ?

Le bit else -10 est juste là car je crois qu'une compréhension de liste écrite comme celle-ci doit se terminer par un else si vous l'oubliez lance une SyntaxError


4 commentaires

ne serait-il pas meilleur et plus lisible si vous utilisez des boucles for normales avec des conditions?


Vous avez raison de dire que l'expression conditionnelle X if Y else Z nécessite un composant else , ou bien elle lève une SyntaxError. Ceci est vrai indépendamment du fait que l'expression soit dans une compréhension de liste. Mais si vous ne vous attendez jamais à ce que Z s'exécute en aucune circonstance, alors il n'y a pas grand chose à avoir une expression conditionnelle. Remplacez simplement X si Y sinon Z par X .


Notez également qu'un if peut apparaître dans une compréhension de liste sans else , par exemple [i * 2 for i in range (10) if i> 5] . Mais ce n'est pas une expression conditionnelle, et elle ne peut pas venir avant le pour .


Le simple vaut mieux que le complexe , Les cas spéciaux ne sont pas assez spéciaux . Penser le problème de manière organisée mène à la solution de @gmds: vérifiez d'abord a , puis vérifiez b , puis remplissez la valeur de l'espace réservé lorsque tout est Aucun . Comme 0 ne doit pas être traité différemment des autres entiers, le code ne doit donc pas comparer les valeurs à 0 .


3 Réponses :


5
votes

Que diriez-vous de ceci?

[7, 9, 7, 15, 1, 2, 0]

Résultat:

[a if a is not None else b if b is not None else 1 for a, b in z]


1 commentaires

Bien, comparé à pas Aucun ici ne le fait certainement lire plus comme l'anglais :-)



2
votes

J'écrirais l'expression comme (appelant le premier élément a et le deuxième b):

[(1 if b is None else b) if a is None else a for a, b in z]

Cela lit immédiatement assez à l'envers, mais c'est ainsi que fonctionne l'expression ternaire. La compréhension de la liste est donc

(1 if b is None else b) if a is None else a


0 commentaires

3
votes

Vous pouvez également utiliser une genexp pour filtrer les éléments qui ne sont pas identiques à None et l'utiliser avec next et une valeur par défaut, par exemple:

[next((el for el in lst if el is not None), 1) for lst in z]           
# [7, 9, 7, 15, 1, 2, 0]


0 commentaires