Reputation: 341
I would like to apply function with multiple arguments to a vector.
It seems that both map()
and map!()
can be helpful.
It works perfect if function has one argument:
f = function(a)
a+a
end
x=[1,2,3,4,5]
map(f, x)
output: [2, 4, 6, 8, 10]
However, it is not clear how to pass arguments to the function, if possible, and the vector to broadcast, if the function has multiple arguments.
f = function(a,b)
a*b
end
However, non of the following working:
b=3
map(f(a,b), x, 3)
map(f, x, 3)
map(f, a=x, b=3)
map(f(a,b), x, 3)
map(f(a,b), a=x,b=3)
Expected output:
[3,6,9,12,15]
Upvotes: 3
Views: 1321
Reputation: 14695
A few other options:
julia> map(Base.splat(func), Iterators.product(3, x))
5-element Vector{Int64}:
3
6
9
12
15
Iterators.product
returns a list of tuples (3, 1)
, (3, 2)
, etc. Since our function func
takes multiple separate arguments and not a tuple, we use Base.splat
on it which takes the tuple and splats it into separate arguments to pass on to func
.
julia> using SplitApplyCombine: product
julia> product(func, x, 3)
5-element Vector{Int64}:
3
6
9
12
15
SplitApplyCombine.jl's product
function can directly map a given function over each combination (Cartesian product) of the given arguments.
julia> map(func, x, Iterators.cycle(3))
5-element Vector{Int64}:
3
6
9
12
15
A difference from the two previous ways is that if the shorter argument was a vector with more than one element in it, the previous methods would apply the function to each combination of elements from the two arguments, whereas this one would behave like Python's zip_longest
, repeating the shorter vector until they were the same length (and then applying the function).
julia> y = [10, 1000];
julia> SplitApplyCombine.product(func, x, y) # previous method
5×2 Matrix{Int64}:
10 1000
20 2000
30 3000
40 4000
50 5000
julia> map(func, x, Iterators.cycle(y))
5-element Vector{Int64}:
10
2000
30
4000
50
Upvotes: 1
Reputation: 69869
Use broadcast - just as you suggested in the question:
julia> f = function(a,b)
a*b
end
#1 (generic function with 1 method)
julia> x=[1,2,3,4,5]
5-element Vector{Int64}:
1
2
3
4
5
julia> b=3
3
julia> f.(x, b)
5-element Vector{Int64}:
3
6
9
12
15
map
does not broadcast, so if b
is a scalar you would manually need to write:
julia> map(f, x, Iterators.repeated(b, length(x)))
5-element Vector{Int64}:
3
6
9
12
15
You can, however, pass two iterables to map
without a problem:
julia> map(f, x, x)
5-element Vector{Int64}:
1
4
9
16
25
Upvotes: 6
Reputation: 51
One possible solution is to create an anonymous function
inside map as follows -->
x = [1, 2, 3, 4, 5]
b = 3
f = function(a, b)
a * b
end
map(x -> f(x, b), x)
which produces below output-->
5-element Vector{Int64}:
3
6
9
12
15
Explanation :-
Anonymous function is taking values from vector as its first argument and 2nd argument is fixed with b = 3
.
Upvotes: 5