Pythonische manier om FOR-lus en IF-statement te combineren

Ik weet hoe ik zowel for-loops als if-statements op afzonderlijke regels moet gebruiken, zoals:

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

En ik weet dat ik een lijstbegrip kan gebruiken om deze te combineren als de uitspraken eenvoudig zijn, zoals:

print([x for x in xyz if x in a])

Maar wat ik nergens kan vinden is een goed voorbeeld (om te kopiëren en van te leren) dat een complexe reeks commando’s demonstreert (niet alleen “print x”) die optreden na een combinatie van een for-lus en enkele if-statements. Iets dat ik zou verwachten ziet eruit als:

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

Is dit gewoon niet de manier waarop python zou moeten werken?


Antwoord 1, autoriteit 100%

Je kunt generator-expressiesals volgt gebruiken:

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

Antwoord 2, autoriteit 10%

Volgens The Zen of Python(als je je afvraagt of je code “Pythonic” is , dat is de plek om naartoe te gaan):

  • Mooi is beter dan lelijk.
  • Expliciet is beter dan impliciet.
  • Eenvoudig is beter dan complex.
  • Vlak is beter dan genest.
  • Leesbaarheid telt.

De Pythonische manier om de sortedte krijgen intersectionvan twee sets is:

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

Of die elementen die xyzzijn maar niet in a:

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

Maar voor een meer gecompliceerde lus kun je deze afvlakken door een welbekende generatorexpressieen/of het aanroepen van een welbekende functie. Alles op één regel proberen te passen is zelden “pythonisch”.


Update volgende aanvullende opmerkingen over uw vraag en het geaccepteerde antwoord

Ik weet niet zeker wat je probeert te doen met enumerate, maar als aeen woordenboek is, wil je waarschijnlijk de toetsen als volgt gebruiken:

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

Antwoord 3, autoriteit 6%

Het volgende is een vereenvoudiging/één voering van het geaccepteerde antwoord:

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

Merk op dat de generatorinlinewerd gehouden. Dit is getest op python2.7en python3.6(let op de haakjes in de print😉 )


Antwoord 4, autoriteit 5%

Persoonlijk vind ik dit de mooiste versie:

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

Bewerken

als u het gebruik van lambda heel graag wilt vermijden, kunt u een toepassing voor gedeeltelijke functies gebruiken en de operatormodule gebruiken (die de functies van de meeste operators biedt).

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)))

Antwoord 5, autoriteit 3%

Ik zou waarschijnlijk gebruiken:

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

Antwoord 6, autoriteit 2%

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

Antwoord 7, autoriteit 2%

U kunt ook generatorengebruiken als generatoruitdrukkingen te ingewikkeld of te complex worden:

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

Antwoord 8

Ik vond Alex’s antwoord, omdat een filterprecies een indienis die op een lijst wordt toegepast, dus als u een subset van een lijst met een voorwaarde wilt verkennen, lijkt dit de meest natuurlijke manier

mylist = [1,2,3,4,5]
another_list = [2,3,4]
wanted = lambda x:x in another_list
for x in filter(wanted, mylist):
    print(x)

deze methode is handig voor het scheiden van zorgen, als de conditiefunctie verandert, is de enige code om mee te rommelen de functie zelf

mylist = [1,2,3,4,5]
wanted = lambda x:(x**0.5) > 10**0.3
for x in filter(wanted, mylist):
    print(x)

De generator-methode lijkt beter als je geen leden van de lijst wilt, maar een wijziging van die leden, die beter past bij een generator

mylist = [1,2,3,4,5]
wanted = lambda x:(x**0.5) > 10**0.3
generator = (x**0.5 for x in mylist if wanted(x))
for x in generator:
    print(x)

Filters werken ook met generatoren, hoewel het in dit geval niet efficiënt is

mylist = [1,2,3,4,5]
wanted = lambda x:(x**0.5) > 10**0.3
generator = (x**0.9 for x in mylist)
for x in filter(wanted, generator):
    print(x)

Maar het zou natuurlijk nog steeds leuk zijn om zo te schrijven:

mylist = [1,2,3,4,5]
wanted = lambda x:(x**0.5) > 10**0.3
# for x in filter(wanted, mylist):
for x in mylist if wanted(x):
    print(x)

Antwoord 9

Gebruik intersectionof intersection_update

  • kruispunt:

    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)
    

    dan is buw antwoord


Antwoord 10

Een eenvoudige manier om unieke gemeenschappelijke elementen van lijsten a en b te vinden:

a = [1,2,3]
b = [3,6,2]
for both in set(a) & set(b):
    print(both)

Other episodes