0

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?

4
  • 2
    Why do you need to create a lambda for this? What advantages do you feel that gives you? A lambda is nothing more than limited method of creating a function object in an expression. Commented Jan 29, 2016 at 9:01
  • You can't really do what you want, not without very ugly hacks with mutable objects and or expressions. Readabilitywill be severely compromised. Commented Jan 29, 2016 at 9:01
  • It's because of a larger part of the code where there're many different variants of this function, and this function is passed on to another to manipulate x. Commented Jan 29, 2016 at 9:01
  • To give the background, it's from this PR suggestion to convert these functions into some sort of pass-able function into another: github.com/nltk/nltk/pull/1270 Commented Jan 29, 2016 at 9:03

1 Answer 1

2

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)]
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.