Coder Perfect

Pythonic way to combine FOR loop and IF statement

Problem

I know how to use both for loops and if statements on separate lines, such as:

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

And I know I can combine these using a list comprehension when the statements are simple, such as:

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

But I can’t seem to locate a good example (to copy and learn from) illustrating a complex sequence of instructions (not just “print x”) that occur after a for loop and a few if statements are combined. Something along these lines, for example:

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

Isn’t this how python is intended to function?

Asked by ChewyChunks

Solution #1

Generator expressions can be used in the following way:

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

for x in gen:
    print(x)

Answered by Kugel

Solution #2

According to The Zen of Python (which you should consult if you’re unsure whether your code is “Pythonic”):

Getting the sorted intersection of two sets in Python is as follows:

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

Or those xyz elements that aren’t in a:

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

You could flatten the loop by iterating over a well-named generator expression and/or executing a well-named function. It is rarely “Pythonic” to try to fit everything on one line.

I’m not sure what you’re attempting to accomplish with enumerate, but if it’s a dictionary, you should probably utilize the keys, like in:

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

Answered by Johnsyweb

Solution #3

The following is a condensed version of the accepted answer:

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

It’s worth noting that the generator was left in place. This was tested with Python 2.7 and Python 3.6 (note the parens in the print;)).

Even still, it’s a bit of a pain: the x is referenced four times.

Answered by WestCoastProjects

Solution #4

This, in my opinion, is the most attractive version:

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

If you don’t want to utilize lambda, you can use partial function application and the operator module instead (that provides functions of most operators).

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

Answered by Alexander Oh

Solution #5

I’d most likely use:

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

Answered by Wim Feijen

Post is based on https://stackoverflow.com/questions/6981717/pythonic-way-to-combine-for-loop-and-if-statement