I want to replicate the following JavaScript code in Python:
let a = [0, 4, 5]
b = a.map(x => {
if(x < 3) return 0
else return 1
})
Any idea how I can do this?
I'm not sure how execute a code block in a map function.
You can either make a function, or use a lambda function like this:
>>> a = [0, 4, 5]
>>> b = map(lambda x: 0 if x < 3 else 1, a)
>>> b
[0, 1, 1]
The only kind of anonymous functions in Python are lambdas, and they're limited to being only an expression, if you want a proper function you have to give it a name:
def map_f(x):
if x < 3:
return 0
else:
return 1
b = map(map_f, a)
Personally, I prefer list comprehension to the map function.
>>> a = [0, 4, 5]
>>> [int(x >= 3) for x in a]
[0, 1, 1]
They allow you to use whatever expression you want without having to create a function.
Related
I am looking for a way to do assignments in a list comprehension. I would like to rewrite something like the following piece of code into a list comprehension.
I have this "costly" function:
import time
def f(x):
time.sleep(1)
return x + 1
And this loop:
l = []
for value in [1, 2, 3]:
x = f(value)
l.append(x + x)
I would like to rewrite this to a list comprehension:
l = [
f(value) + f(fvalue)
for value in [1, 2, 3]
]
But since calling f(value) is costly, I would like to minimize the number of calls (this following snippet doesn't run):
l = [
(x = f(value))
x + x
for value in [1, 2, 3]
]
I've read about the assignment expression (:=) (https://www.python.org/dev/peps/pep-0572/#changing-the-scope-rules-for-comprehensions) but I can't seem to figure it out.
My approach would be to nest multiple list comprehension, like
l_new = [x * x * y for x, y in [f(value) for value in [1, 2, 3]]]
So f() should only be called once for each value.
Here is another way to fake it:
[x+x for value in [1, 2, 3] for x in [f(value)]]
This can be done with a walrus operator. Note that you need Python 3.8 or later.
l = [x:=10 * value for value in [1, 2, 3]]
With one fast and slow function.
import time
def slow_function(a):
time.sleep(1)
return a + 1
def fast_function(b):
return b + b
l = [
fast_function(x := slow_function(value))
for value in [1, 2, 3]
]
The walrus operator can be skipped in both these examples, but perhaps the real problem would require it.
I want to create a function which returns a function creating an iterator (like something from itertools), but with a parameter set by the outer function.
For example, say I want to take a running sum, but exclude values that are larger than a given cutoff (which is the parameter of the function).
So, say I have a list like this:
x = [1, 1, 1, 1, 25, 1, 1]
And I want a function that would take the running sum, but ignore values greater than 10, to give me an output like this:
y = [1, 2, 3, 4, 4, 5, 6]
This code will do the trick:
t = 10
accumulate(x,lambda x,y:x if y>=t else x+y)
But now I want to make a function which returns a function like the above, where I can pass it the value t as the parameter.
This is what I tried:
def sum_small_nums(t):
def F(x):
new_x = accumulate(x,lambda x,y: x if y>=t else x+y)
return F
Unfortunately this doesn't seem to work. I can create a function from the above, but when I try to call it, I don't get the output I am expecting (e.g. I get 'None' instead of a list):
sum_under_10 = sum_small_nums(10)
print(sum_under_10)
x = [1, 1, 1, 1, 25, 1, 1]
x2 = sum_under_10(x)
print(x2)
returns
<function sum_small_nums.<locals>.F at 0x7feab135a1f0>
None
You're close! Need to return the list from the inner function:
def sum_small_nums(t):
def F(x):
new_x = accumulate(x, lambda x, y: x if y >= t else x + y)
return list(new_x)
return F
When you don't return anything from a function, None is implicitly returned.
Consider following example in JavaScript:
var x = [1, 2, 3]
var y = x
.map(i => i * 2)
.map(i => i * i)
If I would like to call some function that does some external-state manipulation, like logging or publishing message to a topic I would simply use the brackets to get multi-line lambda:
var x = [1, 2, 3]
var y = x
.map(i => i * 2)
.map(i => {
console.log("arg received ": + i)
return i * i
})
As far as I know, such a trivial thing is impossible to do in Python because of single line lambdas and we have to use named functions which sucks because any code reader or code reviewer have to jump between function definition and function usage, even though the function is used only once.
Is there any industry standard for solving such a trivial issue?
Specifically for logging or other "void" functions, you could use or:
>>> lst = [1, 2, 3]
>>> list(map(lambda x: x*x, map(lambda x: print(x) or x, map(lambda x: x*2, lst))))
2
4
6
[4, 16, 36]
Here, a or b is equivalent to a if a else b, and since print(x) evaluates to None, which is not "truthy", the "else" part is returned after the print is executed.
Also works as a (nested) list comprehension/generator:
>>> [print(x) or x*x for x in (x*2 for x in lst)]
2
4
6
[4, 16, 36]
Whether that's good style is a different question, though.
Alternatively, and probably a bit cleaner, define a log/peek/debug function that logs the value and then returns it, to be put anywhere in your map/list-comp chain:
>>> def peek(x, f=print):
... f(x)
... return x
...
>>> [x*x for x in map(peek, (x*2 for x in lst))]
2
4
6
[4, 16, 36]
Python doesn't really have this concept, the best you can do is just to define an inner function right above where you'd use it
def my_func(i):
return i * i
y = map(my_func, map(lambda i: i * i, x))
Hi I want to implement a lambda function in python which gives me back x if x> 1 and 0 otherhwise (relu):
so I have smth. like:
p = [-1,0,2,4,-3,1]
relu_vals = lambda x: x if x>0 else 0
print(relu_vals(p))
It is important to note that I want to pass the value of lambda to a function
but it fails....
You want to use map to apply this function on every element of the list
list(map(relu_vals, p))
gives you
[0, 0, 2, 4, 0, 1]
Also it's better to define the lambda function within map if you are not planning to use it again
print(list(map(lambda x: x if x > 0 else 0, p)))
You program is right, but need some modification.
Try this,
>>> p = [-1,0,2,4,-3,1]
>>> relu_vals = lambda x: x if x>0 else 0
>>> [relu_vals(i) for i in p]
[0, 0, 2, 4, 0, 1]
I want the output of returned values from a function to be extended to a set of lists.
def func():
return [-1,2],[4,1]
f=[1,2]
g=[3,4]
f,g=func() #How make it append
print f,g
#Expected Output:
[1,2,-1,2] [3,4,4,1]
For one list, I can do f.extend(func()) but what about multiple lists.
Creating temporary variables is not preferred.
Why not pass the function two parameters
def func(l1 ,l2):
return l1+[-1,2],l2+[4,1]
f = [1,2]
g = [3,4]
f,g = func(f,g)
print f,g
produces
[1, 2, -1, 2] [3, 4, 4, 1]
However, it may be easier to let the function extend the lists and avoid the return value altogether
def func(l1 ,l2):
l1.extend([-1,2])
l2.extend([4,1])
f = [1,2]
g = [3,4]
func(f,g)
print f,g
If this question is more general, and you cannot modify your function, use zip:
>>> f,g = (x+y for x,y in zip((f,g), func()))
>>> f
[1, 2, -1, 2]
>>> g
[3, 4, 4, 1]