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
Related
I have a tuple like (p1, p2) (for example (5,3) or (2,1))
I want to apply the same operation to each element of the tuple. (Incidentally this operation will give for each element another tuple, so I will have a tuple of tuples but this is not a necessary condition)
First I thought something like
for element in (3,2):
res=function(element)
but first, this doesn't seem a elegant solution and two, I would still have to form a tuple from each res to get a (function(3),function(2)) solution
How can I apply a function (with several arguments) to each element of the tuple once and get a tuple of returned values?
If I understand you question correctly, map should to the job as well:
tuple(map(func, tpl))
where func is a one-argument function you defined.
Now, if you have a function with several arguments you would like to apply to each element, like:
def func(x, y, z): return x*y+z
I assume that 2 elements (let's take y and z) are fixed, while x will be determined by the value in the tuple.
There are two approaches in my view:
Either you define a new function with 2 fixed arguments and map:
def func1(x): return func(x, 3, 2)
tuple(map(func1, tpl))
Or map as follows (I think it is less elegant, but it is a matter of tastes, maybe):
tuple(map(lambda x: func(x, 3, 2), tpl))
One approach uses a list comprehension:
def add_one(x):
return x + 1
tpl = (5, 3)
output = tuple([add_one(x) for x in tpl])
print(output) # (6, 4)
You may consider using the generator comprehension then convert it to tuple:
>>> data = (3, 5, 7, 9)
>>> tuple((function(x) for x in data))
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.
primes = [2,3,5,7..] (prime numbers)
map(lambda x:print(x),primes)
It does not print anything.
Why is that?
I've tried
sys.stdout.write(x)
too, but doesn't work either.
Since lambda x: print(x) is a syntax error in Python < 3, I'm assuming Python 3. That means map returns a generator, meaning to get map to actually call the function on every element of a list, you need to iterate through the resultant generator.
Fortunately, this can be done easily:
list(map(lambda x:print(x),primes))
Oh, and you can get rid of the lambda too, if you like:
list(map(print,primes))
But, at that point you are better off with letting print handle it:
print(*primes, sep='\n')
NOTE: I said earlier that '\n'.join would be a good idea. That is only true for a list of str's.
This works for me:
>>> from __future__ import print_function
>>> map(lambda x: print(x), primes)
2
3
5
7
17: [None, None, None, None]
Are you using Python 2.x where print is a statement, not a function?
Alternatively, you can unpack it by putting * before map(...) like the following
[*map(...)]
or
{*map(...)}
Choose the output you desire, a list or a dictionary.
Another reason why you could be seeing this is that you're not evaluating the results of the map function. It returns a generator (an iterable) that evaluates your function lazily and not an actual list.
primes = [2,3,5,7]
map(print, primes) # no output, because it returns a generator
primes = [2,3,5,7]
for i in map(print, primes):
pass # prints 2,3,5,7
Alternately, you can do list(map(print, primes)) which will also force the generator to be evaluated and call the print function on each member of your list.
#L is a very large list
A = [x/sum(L) for x in L]
When the interpreter evaluates this, how many times will sum(L) be calculated? Just once, or once for each element?
A list comprehension executes the expression for each iteration.
sum(L) is executed for each x in L. Calculate it once outside the list comprehension:
s = sum(L)
A = [x/s for x in L]
Python has no way of knowing that the outcome of sum(L) is stable, and cannot optimize the call away for you.
sum() could be rebound to a different function that returns random values. The elements in L could implement __add__ methods that produce side effects; the built-in sum() would be calling these. L itself could implement a custom __iter__ method that alters the list in-place as you iterate, affecting both the list comprehension and the sum() call. Any of those hooks could rebind sum or give x elements a __div__ method that alters sum, etc.
In other words, Python is too dynamic to accurately predict expression outcomes.
I would opt for Martijn's approach, but thought I'd point out that you can (ab)use a lambda with a default argument and a map if you wanted to retain a "one-liner", eg:
L = range(1, 10)
A = map(lambda el, total=sum(L, 0.0): el / total, L)
For learning purposes, I'm trying to make a function using Python that takes in another function and two arrays as parameters and calls the function parameter on each index of each array parameter. So this should call add on a1[0] & a2[0], a1[1] & a2[1], etc. But all I'm getting back is a generator object. What's wrong?
def add(a,b):
yield a + b
def generator(add,a1,a2):
for i in range(len(a1)):
yield add(a1[i],a2[i])
g = generator(add,a1,a2)
print g.next()
I've also tried replacing what I have for yield above with
yield map(add,a1[i],a2[i])
But that works even less. I get this:
TypeError: argument 2 to map() must support iteration
Your definition of add() is at least strange (I'm leaning twoards calling it "wrong"). You should return the result, not yield it:
def add(a, b):
return a + b
Now, your generator() will work, though
map(add, a1, a2)
is an easier and faster way to do (almost) the same thing. (If you want an iterator rather than a list, use itertools.imap() instead of map().)
You get a generator because your add is a generator. It should be just return a + b.
I'm trying to make a function using Python that takes in another function and two arrays as parameters and calls the function parameter on each index of each array parameter.
def my_function(func, array_1, array_2):
for e_1,e_2 in zip(array_1, array_2):
yield func(e_1,e_2)
Example:
def add(a, b):
return a + b
for result in my_function(add, [1, 2, 3], [9, 8, 7]):
print(result)
will print:
10
10
10
Now, a couple of notes:
The add function can be found in the operator module.
You see that I used zip, take a look at its the doc.
Even though what you actually need is izip() the generator expression under zip() which basically doesn't return a list but an iterator to each value.
my_function is almost like map(), the only difference is that my_function is a generator while map() gives you a list. Once again the stdlib gives you the generator version of map in the itertools module: imap()
Example, my_fuction is just like imap:
from operator import add
from itertools import imap
for result in imap(add, [1, 2, 3], [9, 8, 7]):
print(result)
#10
#10
#10
I obviously suppose that the add function was just a quick example, otherwise check the built-in sum.
As others have said, you are defining add incorrectly and it should return instead of yield. Also, you could import it:
from operator import add
The reason why this doesn't work:
yield map(add, a1[i], a2[i])
Is because map works on lists/iterables and not single values. If add were defined correctly this could work:
yield map(add, [a[i]], [a2[i]])
But you shouldn't actually do that because it's more complicated than it needs to be for no good reason (as Sven Marnach's answer shows, your generator function is just an attempt to implement map so it really shouldn't use map even if it is a learning exercise). Finally, if the point is to make a function that takes a function as a parameter, I wouldn't call the parameter "add"; otherwise, what's the point of making it at all?
def generator(f, a1, a2):
for x, y in zip(a1, a2):
yield f(x, y)
Speaking of which, take a look at zip.