'lifting functions in python
Say you have a function f:integers -> integers
, one should be able to lift this function to act on sets of integers.
I.e. f:sets of integers -> sets of integers
, by f({a,b,...}) = {f(a),f(b),...}
How can one do this succinctly in python? That is, not involving iterables (loops), potentially something more native and order-independent.
I would expect f({a,b,...})
to be the syntax, but it's not. Maybe something like act(f,{a,b,...})
?
Solution 1:[1]
Python 2.7.10
What you described is mapping; it does involve loops in the background, but it achieves your succinctness. Here's an example.
l = [1,2,3]
#f returns n^2
def f(n):
return n*n
l = map(f, l) #[1,4,9]
map
applies the function f
to every element of l
.
map
also works on sets; however, map returns back a list of values e.g. f({x1,x2,x3}) = [f(x1),f(x2),f(x3)]
, in an arbitrary order. You can turn the returned list back into a set by wrapping it as a set
.
Python 3.6
In Python 3.6, map
returns back a map object, and you will need to convert it to your desired typed. This example shows the map object converted to a list.
l = [1,2,3]
def f(n):
return n*n
l = list(map(f, l)) #[1,4,9]
Alternatively, you can reduce the amount of code further using lambda functions, making it more succinct.
l = [1,2,3]
l = map(lambda x:x*x, l)
Where the lambda expression has the functionality f
but used only there and non-existent afterwards.
Solution 2:[2]
The tools you want are map, and in itertools.
For example, to apply f
on a collection c
of elements, you can use
map(f, c)
Note that the application is lazy in Python 3, and eager in Python 2.7. Alternatively, you can also use a lazy comprehension:
g(f(x) for x in c)
Solution 3:[3]
You can pass multiple arguments as well , like this:
def square(*args) :
l = []
for i in args:
l.append(i**2)
return l
It'll return like:
>>>> square(1,2,3,4)
>>>> [1,2,9,16]
>>>> square(1)
>>>> [1]
>>>> square(1,6)
>>>> [1,36]
Solution 4:[4]
In Python currying is not a native feature but you can emulate it using functools.partial
. For instance, you can use partial
to lift a function f: A -> B
to a function f': [A] -> [B]
.
from functools import partial
def f(...):
...
# lift f
f_lifted = partial(map, f)
Solution 5:[5]
from funcy import curry
def lift(fn):
return curry(map)(fn)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | James Lim |
Solution 3 | Ubdus Samad |
Solution 4 | Omni |
Solution 5 | lo tolmencre |