Suvar
Suvar

Reputation: 341

Apply function with multiple arguments to a vector in Julia

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

Answers (3)

Sundar R
Sundar R

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

Bogumił Kamiński
Bogumił Kamiński

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

KARTHIK D K
KARTHIK D K

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

Related Questions