Reputation: 122022
Given the function that takes x
and manipulate x
as such:
>>> x = [5,3,0,0]
>>> j = 1
>>> for i, xi in enumerate(x):
... if xi == 0:
... x[i] = 1.0/2**j
... j+=1
...
>>> x
[5, 3, 0.5, 0.25]
And in a function:
def f(x):
j = 1
for i, xi in enumerate(x):
if xi == 0:
x[i] = 1.0/2**j
j+=1
return x
I want to change it into a lambda function but how is that possible when it uses an extra variable that not in my loop?
Without the complication of j+=1
and considering j
as a constant I could do this:
j = 1
f = lambda x: [1.0/2**j if xi == 0 else xi for i, xi in enumerate(x)]
But I need the j to change when it if statement is made. How can that be achieved in a lambda function?
Upvotes: 0
Views: 70
Reputation: 1121584
You could make j
an itertools.count()
object; each time you call next()
on it it'll yield the next value in the sequence:
from itertools import count
j = count(1)
f = lambda x: [1.0 / 2 ** next(j) if xi == 0 else xi for i, xi in enumerate(x)]
This works because you only ever ask for that next value when x == 0
is true.
However, you now need to reset j
each time you want to use the lambda
. You could incorporate it into your list comprehension as an extra one-element tuple to loop over:
f = lambda x: [1.0 / 2 ** next(j) if xi == 0 else xi
for j in (count(1),)
for i, xi in enumerate(x)]
All this is not all that readable. I'd stick with the def
function object instead.
As a side note, you could use or
to replace the .. if xi == 0 else xi
expression; xi == 0
makes xi
falsey:
f = lambda x: [xi or 1.0 / 2 ** next(j)
for j in (count(1),)
for i, xi in enumerate(x)]
Upvotes: 2