Consider the following list comprehension
[ (x,f(x)) for x in iterable if f(x) ]
This filters the iterable based a condition f
and returns the pairs of x,f(x)
. The problem with this approach is f(x)
is calculated twice.
It would be great if we could write like
[ (x,fx) for x in iterable if fx where fx = f(x) ]
or
[ (x,fx) for x in iterable if fx with f(x) as fx ]
But in python we have to write using nested comprehensions to avoid duplicate call to f(x) and it makes the comprehension look less clear
[ (x,fx) for x,fx in ( (y,f(y) for y in iterable ) if fx ]
Is there any other way to make it more pythonic and readable?
Update
Coming soon in python 3.8! PEP
# Share a subexpression between a comprehension filter clause and its output
filtered_data = [y for x in data if (y := f(x)) is not None]
There is no where
statement but you can "emulate" it using for
:
a=[0]
def f(x):
a[0] += 1
return 2*x
print [ (x, y) for x in range(5) for y in [f(x)] if y != 2 ]
print "The function was executed %s times" % a[0]
Execution:
$ python 2.py
[(0, 0), (2, 4), (3, 6), (4, 8)]
The function was executed 5 times
As you can see, the functions is executed 5 times, not 10 or 9.
This for
construction:
for y in [f(x)]
imitate where clause.