Sungmin Ji
Sungmin Ji

Reputation: 87

How can I use map! in julia?

How can I use map! with a function using vector variables in julia?

Codes below did not work.

Perhaps, there might be a simple solution of below codes,

but I want to use map! in this problem.

 a1 = ones(100, 2)
 a2 = ones(100, 2)
 a3 = ones(100, 2)

 function expe1(v1,v2,v3)
  v1 + v2 + v3
 end

 dest = [zeros(100) for i in 1:2]

 map!(expe1, dest, eachcol(a1), eachcol(a2), eachcol(a3))

Error:

ERROR: MethodError: no method matching map!(::typeof(expe1), ::Vector{Vector{Float64}}, ::Base.Generator{Base.OneTo{Int64}, Base.var"#242#243"{Matrix{Float64}}}, ::Base.Generator{Base.OneTo{Int64}, Base.var"#242#243"{Matrix{Float64}}}, ::Base.Generator{Base.OneTo{Int64}, Base.var"#242#243"{Matrix{Float64}}})
Closest candidates are:
  map!(::F, ::AbstractArray, ::AbstractArray) where F at abstractarray.jl:2924
  map!(::F, ::AbstractArray, ::AbstractArray, ::AbstractArray) where F at abstractarray.jl:2967
  map!(::F, ::AbstractArray, ::AbstractArray...) where F at abstractarray.jl:3024
  ...
Stacktrace:
 [1] top-level scope
   @ REPL[8]:1

Upvotes: 2

Views: 732

Answers (2)

phipsgabler
phipsgabler

Reputation: 20970

There is no method of map! for non-array iterables, because it insists on all arguments being AbstractArrays having the same shape.

To write the result into a destination array without intermediate allocation, you could broadcast-assign it a generator:

julia> dest .= Base.Generator(expe1, eachcol(a1), eachcol(a2), eachcol(a3))
2-element Vector{Vector{Float64}}:
 [3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0  …  3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0]
 [3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0  …  3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0]

Something like this should also work:

function my_map!(f::F, dest::AbstractArray, As...) where F
    for (i, a...) in zip(eachindex(dest), As...)
        val = f(a...)
        @inbounds dest[i] = val
    end
    return dest
end

Upvotes: 3

AboAmmar
AboAmmar

Reputation: 5559

Please check with latest Julia, it works fine with Julia 1.9.0-DEV:

map!(expe1, dest, eachcol(a1), eachcol(a2), eachcol(a3))
2-element Vector{Vector{Float64}}:
 [3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0  …  3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0]
 [3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0  …  3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0]

julia> VERSION
v"1.9.0-DEV.1332"

And you could just do:

expe1(eachcol(a1), eachcol(a2), eachcol(a3))
2-element Vector{Vector{Float64}}:
 [3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0  …  3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0]
 [3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0  …  3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0]

Upvotes: 2

Related Questions