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
3 Réponses :
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]
Bien, comparé à pas Aucun ici ne le fait certainement lire plus comme l'anglais :-)
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
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]
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 composantelse
, 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 simplementX si Y sinon Z
parX
.Notez également qu'un
if
peut apparaître dans une compréhension de liste sanselse
, 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 lepour
.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'aborda
, puis vérifiezb
, puis remplissez la valeur de l'espace réservé lorsque tout estAucun
. Comme0
ne doit pas être traité différemment des autres entiers, le code ne doit donc pas comparer les valeurs à0
.