web-dev-qa-db-fra.com

Manière pythonique de combiner une boucle FOR et une instruction IF

Je sais comment utiliser les instructions for loops et if sur des lignes séparées, 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, c’est un bon exemple n’importe où (pour copier et apprendre) illustrant un ensemble complexe de commandes (pas seulement "print x") qui surviennent à la suite d’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 python est censé fonctionner?

236
ChewyChunks

Vous pouvez utiliser expressions du générateur comme ceci:

gen = (x for x in xyz if x not in a)

for x in gen:
    print x
282
Kugel

Selon Le zen de Python (si vous vous demandez si votre code est "Pythonic", c'est l'endroit où aller):

  • Beau vaut mieux que moche.
  • Explicite est meilleur qu'implicite.
  • Simple c'est mieux que complexe.
  • Flat est mieux que niché.
  • La lisibilité compte.

La manière pythonique d'obtenir le sortedintersection de deux set s est:

>>> sorted(set(a).intersection(xyz))
[0, 4, 6, 7, 9]

Ou ces éléments qui sont xyz mais pas dans a:

>>> sorted(set(xyz).difference(a))
[12, 242]

Mais pour une boucle plus compliquée, vous pouvez l'aplatir en itérant sur une expression bien nommée générateur et/ou en appelant une fonction bien nommée. Essayer de tout adapter sur une ligne est rarement "Pythonic".


Mise à jour des commentaires supplémentaires suivants sur votre question et de la réponse acceptée

Je ne suis pas sûr de ce que vous essayez de faire avec enumerate , mais si a est un dictionnaire, vous voudrez probablement utiliser les clés, comme ceci:

>>> a = {
...     2: 'Turtle Doves',
...     3: 'French Hens',
...     4: 'Colly Birds',
...     5: 'Gold Rings',
...     6: 'Geese-a-Laying',
...     7: 'Swans-a-Swimming',
...     8: 'Maids-a-Milking',
...     9: 'Ladies Dancing',
...     0: 'Camel Books',
... }
>>>
>>> xyz = [0, 12, 4, 6, 242, 7, 9]
>>>
>>> known_things = sorted(set(a.iterkeys()).intersection(xyz))
>>> unknown_things = sorted(set(xyz).difference(a.iterkeys()))
>>>
>>> for thing in known_things:
...     print 'I know about', a[thing]
...
I know about Camel Books
I know about Colly Birds
I know about Geese-a-Laying
I know about Swans-a-Swimming
I know about Ladies Dancing
>>> print '...but...'
...but...
>>>
>>> for thing in unknown_things:
...     print "I don't know what happened on the {0}th day of Christmas".format(thing)
...
I don't know what happened on the 12th day of Christmas
I don't know what happened on the 242th day of Christmas
31
Johnsyweb

Personnellement, je pense que c'est la version la plus jolie:

a = [2,3,4,5,6,7,8,9,0]
xyz = [0,12,4,6,242,7,9]
for x in filter(lambda w: w in a, xyz):
  print x

Modifier

si vous voulez vraiment é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

from operator import contains
from functools import partial
print(list(filter(partial(contains, a), xyz)))
13
Alex

Ce qui suit est une simplification/une ligne de la réponse acceptée:

a = [2,3,4,5,6,7,8,9,0]
xyz = [0,12,4,6,242,7,9]

for x in (x for x in xyz if x not in a):
    print(x)

12
242

Notez que la generator a été conservée inline. Ceci a été testé sur python2.7 et python3.6 (notez les parenthèses dans le print;))

12
javadba

J'utiliserais probablement:

for x in xyz: 
    if x not in a:
        print x...
9
Wim Feijen
a = [2,3,4,5,6,7,8,9,0]
xyz = [0,12,4,6,242,7,9]  
set(a) & set(xyz)  
set([0, 9, 4, 6, 7])
9
Kracekumar

Vous pouvez utiliser generators aussi, si les expressions de générateur deviennent trop impliquées ou complexes:

def gen():
    for x in xyz:
        if x in a:
            yield x

for x in gen():
    print x
5
Lauritz V. Thaulow

Utilisez intersection ou intersection_update

  • intersection:

    a = [2,3,4,5,6,7,8,9,0]
    xyz = [0,12,4,6,242,7,9]
    ans = sorted(set(a).intersection(set(xyz)))
    
  • intersection_update:

    a = [2,3,4,5,6,7,8,9,0]
    xyz = [0,12,4,6,242,7,9]
    b = set(a)
    b.intersection_update(xyz)
    

    alors b est votre réponse

2
Chung-Yen Hung