Je sais comment utiliser à la fois les boucles for et les instructions if sur des lignes distinctes, telles que:
>>> a = [2,3,4,5,6,7,8,9,0]
... xyz = [0,12,4,6,242,7,9]
... for x in xyz:
... if x in a:
... print(x)
0,4,6,7,9
Et je sais que je peux utiliser une compréhension de liste pour les combiner lorsque les déclarations sont simples, telles que:
print([x for x in xyz if x in a])
Mais ce que je ne trouve pas est un bon exemple n'importe où (pour copier et apprendre) démontrant un ensemble complexe de commandes (pas seulement "print x") qui se produisent après une combinaison d'une boucle for et de quelques instructions if. Quelque chose que j'attendrais ressemble à:
for x in xyz if x not in a:
print(x...)
N'est-ce pas ainsi que le python est censé fonctionner?
python
loops
if-statement
for-loop
ChewyChunks
la source
la source
for
boucle etif
instruction explicites .x in a
est lent s'ila
s'agit d'une liste.Réponses:
Vous pouvez utiliser des expressions de générateur comme ceci:
la source
gen = (y for (x,y) in enumerate(xyz) if x not in a)
renvoie >>>12
lorsque je tapefor x in gen: print x
- alors pourquoi le comportement inattendu avec énumérer?for x in xyz if x:
for x in (x for x in xyz if x not in a):
fonctionne pour moi, mais pourquoi vous ne devriez pas être en mesure de le fairefor x in xyz if x not in a:
, je ne suis pas sûr ...Selon The Zen of Python (si vous vous demandez si votre code est "Pythonic", c'est l'endroit où aller):
La façon Pythonique d'obtenir les deux s est:
sorted
intersection
set
Ou ces éléments qui sont
xyz
mais pas dansa
:Mais pour une boucle plus compliquée, vous pouvez l'aplatir en itérant sur une expression de générateur bien nommée et / ou en appelant une fonction bien nommée. Essayer de tout mettre sur une seule ligne est rarement "Pythonic".
Mise à jour suite aux commentaires supplémentaires sur votre question et la réponse acceptée
Je ne sais pas avec quoi vous essayez de faire
enumerate
, mais s'ila
s'agit d'un dictionnaire, vous voudrez probablement utiliser les clés, comme ceci:la source
Je pense personnellement que c'est la plus jolie version:
Éditer
si vous souhaitez éviter d'utiliser lambda, vous pouvez utiliser une application de fonction partielle et utiliser le module opérateur (qui fournit les fonctions de la plupart des opérateurs).
https://docs.python.org/2/library/operator.html#module-operator
la source
filter(a.__contains__, xyz)
. Habituellement, lorsque les gens utilisent lambda, ils ont vraiment besoin de quelque chose de beaucoup plus simple.__contains__
est une méthode comme les autres, seulement c'est une méthode spéciale , ce qui signifie qu'elle peut être appelée indirectement par un opérateur (in
dans ce cas). Mais il peut aussi être appelé directement, il fait partie de l'API publique. Les noms privés sont spécifiquement définis comme ayant au plus un trait de soulignement final, pour fournir une exception pour les noms de méthodes spéciales - et ils sont sujets à la manipulation de noms lorsqu'ils sont lexicalement dans les étendues de classe. Voir docs.python.org/3/reference/datamodel.html#specialnames et docs.python.org/3.6/tutorial/classes.html#private-variables .in
est distribuée séparément par l'opérande droit). En outre, notez que la méthodeoperator
exporte égalementcontains
sous le nom__contains__
, donc ce n'est certainement pas un nom privé. Je pense que vous devrez juste apprendre à vivre avec le fait que tous les doubles soulignés ne signifient pas "éloignez-vous". : -]lambda
besoins doivent inclurenot
:lambda w: not w in a, xyz
Ce qui suit est une simplification / une ligne de la réponse acceptée:
Notez que le a
generator
été maintenu en ligne . Cela a été testépython2.7
etpython3.6
(notez les parens dans leprint
;))la source
J'utiliserais probablement:
la source
pythonic
Je peux coder fonctionnellement dans toutes les autres langues que j'utilise (scala, kotlin, javascript, R, swift, ..) mais difficile / maladroit en pythonla source
import time a = [2,3,4,5,6,7,8,9,0] xyz = [0,12,4,6,242,7,9] start = time.time() print (set(a) & set(xyz)) print time.time() - start
if x in ignore: ...
.if set(a) - set(ignore) == set([]):
c'est peut-être pourquoi c'est beaucoup plus lent que de vérifier l'adhésion. Je testerai cela à l'avenir sur un exemple beaucoup plus simple que celui que j'écris.Vous pouvez également utiliser des générateurs , si les expressions de générateur deviennent trop impliquées ou complexes:
la source
Utilisez
intersection
ouintersection_update
intersection :
intersection_update :
alors
b
est ta réponsela source
J'ai aimé la réponse d'Alex , car un filtre est exactement un s'il est appliqué à une liste, donc si vous voulez explorer un sous-ensemble d'une liste en fonction d'une condition, cela semble être le moyen le plus naturel
cette méthode est utile pour la séparation des préoccupations, si la fonction de condition change, le seul code à manipuler est la fonction elle-même
La méthode du générateur semble meilleure lorsque vous ne voulez pas de membres de la liste, mais une modification desdits membres, qui semble plus adaptée à un générateur
De plus, les filtres fonctionnent avec des générateurs, bien que dans ce cas ce ne soit pas efficace
Mais bien sûr, ce serait quand même bien d'écrire comme ceci:
la source
Un moyen simple de trouver des éléments communs uniques des listes a et b:
la source