从映射函数返回多个值

War*_*ity 5 arrays function anonymous-function julia

假设我有一个名为 trig 的函数,它返回两个输出:

function trig(x)
    return(sin(x), cos(x))
end
Run Code Online (Sandbox Code Playgroud)

如果我想评估多个值的三角函数,我可以使用 map 函数:

julia> out = map(trig, (0:(pi/12):(pi/2)))
Run Code Online (Sandbox Code Playgroud)

out 是一个 7 元素数组,每个元素中都有一个包含两个元素的元组:

julia> out
7-element Array{Tuple{Float64,Float64},1}:
(0.0,1.0)
(0.258819,0.965926)
(0.5,0.866025)
(0.707107,0.707107)
(0.866025,0.5)
(0.965926,0.258819)
(1.0,6.12323e-17)
Run Code Online (Sandbox Code Playgroud)

我的问题是:解开正弦和余弦的最佳方法是什么,以便我有两个数组,每个数组有 7 个元素?是否可以在不创建多余的元组数组的情况下广播三角函数,而是直接创建我真正感兴趣的两个数组?

目前,我再次调用 map 以便从 out 中提取值以填充我想要的数组,但我认为这不是执行此操作的最佳方法:

sines = map(x->x[1], out)
cosines = map(x->x[2], out)
Run Code Online (Sandbox Code Playgroud)

出于本问题的目的,假设 trig 是一个计算量大的函数。因此,请不要给我一个需要多次评估 trig 的答案。

War*_*ity 1

感谢蒂姆分享您对之前一个问题的答案,在问这个问题之前,我在搜索中肯定忽略了这个问题。在今天之前,我从未听说过 getIndex 函数,但似乎 getindex 就是我想要的函数,前提是我通过在前面加一个点来对其进行向量化:

julia> @time sine_map = map(x->x[1], out)
  0.051494 seconds (13.32 k allocations: 602.941 KB)
7-element Array{Float64,1}:
 0.0
 0.258819
 0.5
 0.707107
 0.866025
 0.965926
 1.0

julia> @time sine_geti = getindex.(out, 1)
  0.029560 seconds (9.24 k allocations: 416.910 KB)
7-element Array{Float64,1}:
 0.0
 0.258819
 0.5
 0.707107
 0.866025
 0.965926
 1.0

julia> @time cosine_map = map(x->x[2], out)
  0.037328 seconds (13.32 k allocations: 602.941 KB)
7-element Array{Float64,1}:
 1.0
 0.965926
 0.866025
 0.707107
 0.5
 0.258819
 6.12323e-17

julia> @time cosey_geti = getindex.(out, 2)
  0.024785 seconds (9.24 k allocations: 416.910 KB)
7-element Array{Float64,1}:
 1.0
 0.965926
 0.866025
 0.707107
 0.5
 0.258819
 6.12323e-17
Run Code Online (Sandbox Code Playgroud)

将分配数量减少 30% 是不容小觑的。谢谢。

我认为我可以安全地使其更加简洁:

@time sines, cosines = map(x->getindex.(out, x), 1:2)
  0.062047 seconds (20.81 k allocations: 956.831 KB)
2-element Array{Array{Float64,1},1}:
 [0.0,0.258819,0.5,0.707107,0.866025,0.965926,1.0]
 [1.0,0.965926,0.866025,0.707107,0.5,0.258819,6.12323e-17]
Run Code Online (Sandbox Code Playgroud)

感谢 Colin T Bowers 建议我可以为三角函数定义自定义方法。如果 getindex 无法提供我想要的性能,我肯定会考虑这样做。

  • 不要在全球范围内进行基准测试。将代码包装在函数中或使用“BenchmarkTools”和“@btime getindex.($out, 1)”代替。 (2认同)