Питонический способ комбинирования цикла FOR и IF

Я знаю, как использовать как для циклов, так и для операторов на отдельных строках, например:

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

И я знаю, что могу использовать понимание списка, чтобы объединить их, когда инструкции просты, например:

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

Но то, что я не могу найти, является хорошим примером в любом месте (для копирования и обучения), демонстрирующим сложный набор команд (а не только "print x" ), которые возникают после комбинации цикла for и некоторых операторов if. То, что я ожидаю, выглядит следующим образом:

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

Это не так, как должен работать python?

Ответ 2

В соответствии с Zen of Python (если вам интересно, является ли ваш код "Pythonic", это место для перехода):

  • Красивая лучше, чем уродливая.
  • Явный лучше, чем неявный.
  • Простой лучше, чем сложный.
  • Плоский лучше, чем вложенный.
  • Показатели удобочитаемости.

Pythonic способ получить sorted intersection двух set является:

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

Или те элементы, которые xyz, но не в a:

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

Но для более сложного цикла вы можете сгладить его, итерации над выраженным выражением выражений и/или вызывать функцию с хорошо подобранными функциями. Попытка вместить все на одной линии редко "Pythonic".


Обновление следующих дополнительных комментариев по вашему вопросу и принятого ответа

Я не уверен, что вы пытаетесь сделать с enumerate, но если a является словарем, вы, вероятно, захотите использовать ключи, например:

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

Ответ 3

Я лично думаю, что это самая красивая версия:

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

Edit

если вы очень заинтересованы в том, чтобы избегать использования лямбды, вы можете использовать частичное применение функции и использовать модуль оператора (который обеспечивает функции большинства операторов).

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

Ответ 4

Ниже приведено упрощение/один вкладыш из принятого ответа:

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

Обратите внимание, что generator оставался встроенным. Это было проверено на python2.7 и python3.6 (обратите внимание на символы в print;))

Ответ 5

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

Ответ 6

Я бы, вероятно, использовал:

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

Ответ 7

Вы также можете использовать генераторы, если выражения генератора слишком сложны или сложны:

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

for x in gen():
    print x

Ответ 8

Используйте intersection или intersection_update

  • пересечение:

    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)
    

    тогда b - ваш ответ

Ответ 9

Мне понравился ответ Алекса, потому что фильтр является в точности , если применяется к списку, поэтому, если вы хотите исследовать подмножество списка с учетом условия, это, кажется, самый естественный способ

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)

этот метод полезен для разделения проблем, если изменяется функция условия, единственный код, с которым нужно поиграться, - это сама функция

mylist = [1,2,3,4,5]

wanted = lambda x:(x**0.5) > 10**0.3

for x in filter(wanted, mylist):
    print(x)

Метод генератора выглядит лучше, когда вам не нужны члены списка, а есть модификация указанных членов, которая кажется более подходящей для генератора

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)

Кроме того, фильтры работают с генераторами, хотя в этом случае они не эффективны

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)

Но, конечно, было бы неплохо написать так:

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)