Warning This is a bit confusing, but does the job. I will use an example to explain this.
Say expensive_function = math.sin
infinite generator = collections.count(0.1,0.1)
then
[z for z in (y if y < 5 else next(iter([])) for y in (math.sin(x) for x in itertools.count(0.1,0.1)))]
is an
[0.09983341664682815, 0.19866933079506122, 0.2955202066613396, 0.3894183423086505, 0.479425538604203]
So your problem comes down to
[z for z in (y if y < 0.5 else next(iter([])) \ for y in (expensive_function(x) for x in generator))]
The trick is to force a StopIteration
from the generator and nothing more elegant than next(iter([]))
Here expensive_function
is called only once per iteration.
Extend an infinite generator using a finite generator with a stop condition. Since the generator will not allow raise StopIteration
, we choose a minimized method, i.e. next(iter([]))
And now you have a finite generator that you can use in understanding List
Since the OP was associated with the application of the above method for the monotonic function, a fictitious nonmonotonic function is given here.
f(x) = random.randint(1,100)*x
function f(x) = random.randint(1,100)*x
Stop condition = < 7
[z for z in (y if y < 7 else next(iter([])) for y in (random.randint(1,10)*x for x in itertools.count(0.1,0.1)))] [0.9, 0.6000000000000001, 1.8000000000000003, 4.0, 0.5, 6.0, 4.8999999999999995, 3.1999999999999997, 3.5999999999999996, 5.999999999999999]
Btw: sin
in the true sense is nonmonotonic over the entire range (0,2pi)