I have some code as shown below.
import math
square_root = lambda x: math.sqrt(x)
list = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
map(square_root,list)
Output:
[1.0,
1.4142135623730951,
1.7320508075688772,
2.0,
2.23606797749979,
2.449489742783178,
2.6457513110645907,
2.8284271247461903,
3.0,
3.1622776601683795,
3.3166247903554,
3.4641016151377544,
3.605551275463989,
3.7416573867739413,
3.872983346207417,
4.0]
Now I want to use power instead of square_root
import math
power = lambda x: math.power(x,n)
list = [1,2,3,4,5]
map(power,list,2)
And I get the following error? How do I use two arguments with map?
TypeError Traceback (most recent call last)
/home/AD/karthik.sharma/ws_karthik/trunk/ in ()
----> 1 map(power,list,2)
TypeError: argument 3 to map() must support iteration
One way to do this is the following:
power = lambda x, n: math.pow(x,n)
list = [1,2,3,4,5]
map(power,list,[2]*len(list))
The expression [2]*len(list) creates another list the same length as your existing one, where each element contains the value 2. The map function takes an element from each of its input lists and applies that to your power function.
Another way is:
power = lambda x, n: math.pow(x,n)
list = [1,2,3,4,5]
map(lambda x: power(x, 2),list)
which uses partial application to create a second lambda function that takes only one argument and raises it to the power 2.
Note that you should avoid using the name list as a variable because it is the name of the built-in Python list type.
Like this:
power = lambda x, n: math.pow(x,n)
list = [1,2,3,4,5]
map(lambda x: power(x, 2), list)
List comprehensions are another option:
list = [1,2,3,4,5]
[math.pow(x,2) for x in list]
import math
power = lambda n: lambda x: math.pow(x,n)
list = [1,2,3,4,5]
map(power(2),list)
Related
I have a list with different values and a dictionary with different equations. I want to iterate with a for-loop through the list values and calculate a given equation. The example is below:
list = [1,2,3,4,5]
d ={"equation1": 2*x+3,
"equation2": 3+4*x}
for x in list:
y= d["equation1"]
print(y)
the output is as you can see below:
5
5
5
5
5
When I put the dictionary into the forloop like the sample below, the right values are calculated:
list = [1,2,3,4,5]
for x in list:
d ={"equation1": 2*x+3,
"equation2": 3+4*x}
y= d["equation1"]
print(y)
Result:
5
7
9
11
13
How can I realise the right results with the dictionary outside the for-loop?
In your first example:
list = [1,2,3,4,5]
d ={"equation1": 2*x+3,
"equation2": 3+4*x}
This can only work if you somehow defined x previously, so you probably didn't share all of your relevant code.
Something like 2*x+3 gets evaluated immediately, so if x == 1, you'd get the result 5, as you suggest you do.
You could create a dict with lambda expressions:
d ={"equation1": lambda x: 2*x+3,
"equation2": lambda x: 3+4*x}
But I wouldn't recommend it as good code. If you do though, this works:
list = [1,2,3,4,5]
d ={"equation1": lambda x: 2*x+3,
"equation2": lambda x: 3+4*x}
for x in list:
y = d["equation1"](x)
print(y)
Note how on the line y = d["equation1"](x) x gets passed to the function accessed with d["equation1"] - a lambda expression is a simple function and the ones defined in the dict expect a single parameter.
A more appropriate solution would be:
def equation1(x):
return 2*x+3
def equation2(x):
return 3+4*x
xs = [1,2,3,4,5]
for x in xs:
y = equation1(x)
print(y)
And then if you have reason to refer to your functions with a dict from somewhere:
xs = [1,2,3,4,5]
funs = {
'equation1': equation1,
'equation2': equation2
}
for x in xs:
y = funs['equation1'](x)
print(y)
The problem you have is that the expressions 2*x+3 and 3+4*x aren't something you can store in a dictionary. Rather, they get computed immediately, with whatever value of x is available when the dictionary is created. They do not use the value of x when the value gets looked up later.
If you want to store some code, like those expressions, to be run later, the natural way to do it in Python is using a function. The lambda keyword even lets you create functions that only evaluate a single expression, which is exactly what you want.
Try:
d = {"equation1": lambda: 2*x+3,
"equation2": lambda: 3+4*x}
for x in list:
d ={"equation1": 2*x+3,
"equation2": 3+4*x}
y = d["equation1"]() # note, here we're calling the lambda function
print(y)
A few other notes:
It might make sense to use a different container than a dictionary for d, since your equation names don't appear to have a great deal of meaning. If you just want to index them by integer (e.g. 1 instead of "equation1"), a list is a much more natural choice.
Also, your equations currently pick the x value freely out of the enclosing namespace. It might be cleaner to pass in the x value as an argument to the lambda function. Grismar's very nice answer covers how to do this for x, so I won't give any redundant example code. Passing the values the equation needs as arguments does require a stricter "contract" to be established between the calling code and the equations though, as if one equation expects there to be a y or z variable defined, you need to know to pass it in as an argument.
Asssume I have a function in python which returns the power of 2 of its input
def f(x):
return x**2
Assume also I have a vector of integers 1,2,3,4,5
I = asarray(list(range(1,6)))
Now I want to evaluate the function f with all inputs from I and the results should be in a vector of dimensions 5 (A 1x5 array in Python). My desired result is then: [1,4,9,16,25].
Can I get this result WITHOUT the use of a for or any other loop?
I have used array package
directly from the pythontips website...
use the map function!
squared = list(map(lambda x: x**2, I))
if you want to use your function inside the map-function, just do squared = list(map(f, I)).
There are generally two classical ways to apply a function to all elements of an iterable and store the results in a list. The more flexible one is a list comprehension:
result = [f(x) for x in range(1, 6)] # the upper bound is exclusive!
The other option is map which allows a more concise notation, in particular if you have a named function available and do not need to use a lambda or the like:
result = map(f, range(1, 6)) # Python2: returns list
result = list(map(f, range(1, 6))) # Python3: return iterator, so cast
I am new to Python and practicing basics. I am using a lambda expression to take two arguments and performing square operations on them (eg: var ** 2). The two arguments are coming from the zip(list1, list2). I am getting TypeError for this. I tried searching for the solution but didn't get any. I even tried writing lambda arguments in parenthesis (eg: lambda (v1,v2):) but that threw SyntaxError.
Below is the python code:
list1 = [1,2,3,4]
list2 = [5,6,7,8]
print ( list(map(lambda v1,v2: (v1**2, v2**2), list(zip(list1, list2)))) )
Error:
TypeError Traceback (most recent call last)
<ipython-input-241-e93d37efc752> in <module>()
1 list1 = [1,2,3,4]
2 list2 = [5,6,7,8]
----> 3 print ( list(map(lambda v1,v2: (v1**2, v2**2), list(zip(list1, list2)))) )
TypeError: <lambda>() missing 1 required positional argument: 'v2'
You're giving a single list as argument to map, thus map calls your lambda with one element of the list at a time - that is one argument, even though it is a tuple. What you probably want is:
print ( list(map(lambda v: (v[0]**2, v[1]**2), zip(list1, list2))) )
so that your item from the list is passed as a sole argument to lambda.
If you insist on the two-argument lambda, discard zip and pass your lists directly to map as separate arguments:
print ( list(map(lambda v1,v2: (v1**2, v2**2), list1, list2)) )
In your print, map will cal the function lambda on a list of tuples (as list(zip(list1, list2)) produce a list of tuples).
So for instance you can do :
print(list(map(lambda(v1,v2): (v1**2, v2**2), list(zip(list1, list2)))))
Your lambda function will use the tuple (v1,v2) as parameters, instead of two parameters.
So I'm trying to do this.
a = []
map(lambda x: a.append(x),(i for i in range(1,5)))
I know map takes a function but so why doesn't it append to the list? Or is append not a function?
However printing a results to a still being empty
now an interesting thing is this works
a = []
[a.append(i) for i in range(5)]
print(a)
aren't they basically "saying" the same thing?
It's almost as if that list comprehension became some sort of hybrid list-comprehension function thing
So why doesn't the lambda and map approach work?
I am assuming you are using Python 3.x , the actual reason why your code with map() does not work is because in Python 3.x , map() returns a generator object , unless you iterate over the generator object returned by map() , the lambda function is not called . Try doing list(map(...)) , and you should see a getting filled.
That being said , what you are doing does not make much sense , you can just use -
a = list(range(5))
append() returns None so it doesn't make sense using that in conjunction with map function. A simple for loop would suffice:
a = []
for i in range(5):
a.append(i)
print a
Alternatively if you want to use list comprehensions / map function;
a = range(5) # Python 2.x
a = list(range(5)) # Python 3.x
a = [i for i in range(5)]
a = map(lambda i: i, range(5)) # Python 2.x
a = list(map(lambda i: i, range(5))) # Python 3.x
[a.append(i) for i in range(5)]
The above code does the appending too, however it also creates a list of None values as the size of range(5) which is totally a waste of memory.
>>> a = []
>>> b = [a.append(i) for i in range(5)]
>>> print a
[0, 1, 2, 3, 4]
>>> print b
[None, None, None, None, None]
The functions map and filter have as first argument a function reference that is called for each element in the sequence (list, tuple, etc.) provided as second argument AND the result of this call is used to create the resulting list
The function reduce has as first argument a function reference that is called for first 2 elems in the sequence provided as second argument AND the result is used together with the third elem in another call, then the result is used with the fourth elem, and so on. A single value results in the end.
>>> map(lambda e: e+10, [i for i in range(5)])
[10, 11, 12, 13, 14]
>>> filter(lambda e: e%2, [i for i in range(5)])
[1, 3]
>>> reduce(lambda e1, e2: e1+e2, [i for i in range(5)])
10
Explanations:
map example: adds 10 to each elem of list [0,1,2,3,4]
filter example: keeps only elems that are odd of list [0,1,2,3,4]
reduce example: add first 2 elems of list [0,1,2,3,4], then the result and the third elem of list, then the result and fourth elem, and so on.
This map doesn't work because the append() method returns None and not a list:
>>> a = []
>>> type(a.append(1))
<class 'NoneType'>
To keep it functional why not use reduce instead?
>>> from functools import reduce
>>> reduce(lambda p, x: p+[x], (i for i in range(5)), [])
[0, 1, 2, 3, 4]
Lambda function will not get triggered unless you wrap the call to map function in list() like below
list(map(lambda x: a.append(x),(i for i in range(1,5))))
map only returns a generator object which needs to be iterated in order to create a list. Above code will get the lambda called.
However this code does not make much sense considering what you are trying to achieve
I want to apply a list of lambda functions to a single element using an iterable that has to be created with yield.
The list of lambda functions would have something like:
[<function <lambda> at 0x1d310c8>, <function <lambda> at 0x1d355f0>]
And I want to apply every function, from left to right , to a single element using yield to construct an iterable to iterate the list
def apply_all(functions, item):
for f in functions:
yield f(item)
Example usage:
functions = [type, id, hex]
for result in apply_all(functions, 55):
print result
gives
<type 'int'>
20326112
0x37
Give this a shot:
def lambda_apply(unnamed_funcs, element):
for unnamed in unnamed_funcs:
yield unnamed(element)
>>> l = [lambda x: x**2, lambda x: 2*x]
>>> el = 5
>>> for y in lambda_apply(l, el):
... print y
...
25
10
Note that this works not only for a list of unnamed functions, but any list of functions of arity 1. This is because all functions, named or not, are first class objects in python. You can store them in a list, and use them later, as demonstrated above.
The answer could be formulated as
import numpy as np
def apply_funcs( funcs, val ):
for func in funcs:
yield func(val)
my_funcs = [lambda x: np.cos(x), np.sin, np.tan]
my_val = 0.1
for res in apply_funcs( my_funcs, my_val ):
print res
where the apply_funcs function does the trick and the rest is just for demonstration purposes.
Do you necessarily need a yield statement?
Because there is another way to create generator: to use ().
applied_it = (f(item) for f in functions)
def apply(value, lambda_list):
for function in lambda_list:
yield (function(value))