矢量喷溅

时间:2019-03-21 17:44:42

标签: julia

我希望能够以向量化的方式将一个元组数组喷射到一个函数中。例如,如果我具有以下功能,

function foo(x, y)
    x + y
end

和以下元组数组,

args_array = [(1, 2), (3, 4), (5, 6)]

然后我可以使用列表理解来获得所需的结果:

julia> [foo(args...) for args in args_array]
3-element Array{Int64,1}:
  3
  7
 11

但是,我希望能够对此操作使用点矢量化表示法:

julia> foo.(args_array...)
ERROR: MethodError: no method matching foo(::Int64, ::Int64, ::Int64)

但是如您所见,该特定语法不起作用。有矢量化的方法可以做到这一点吗?

3 个答案:

答案 0 :(得分:8)

foo.(args_array...)不起作用,因为它正在这样做:

foo.((1, 2), (3, 4), (5, 6))
# which is roughly equivalent to
[foo(1,3,5), foo(2,4,6)]

换句话说,它将args_array的每个元素作为一个单独的参数,然后在这些参数上广播foo。您想直接在元素上广播foo。问题在于运行:

foo.(args_array)
# is roughly equivalent to:
[foo((1,2)), foo((3,4)), foo((5,6))]

换句话说,广播语法只是将每个元组作为单个参数传递给foo。我们可以使用一个简单的中间函数来解决该问题:

julia> bar(args) = foo(args...);

julia> bar.(args_array)
3-element Array{Int64,1}:
  3
  7
 11

现在,这就是您想要的!如果不想的话,甚至不需要构造第二个参数。这是完全等效的:

julia> (args->foo(args...)).(args_array)
3-element Array{Int64,1}:
  3
  7
 11

实际上,您可以很容易地对此进行概括:

julia> splat(f) = args -> f(args...);

julia> (splat(foo)).(args_array)
3-element Array{Int64,1}:
  3
  7
 11

答案 1 :(得分:1)

您可以zip args_array,它可以有效地对元组数组进行转置:

julia> collect(zip(args_array...))
2-element Array{Tuple{Int64,Int64,Int64},1}:
 (1, 3, 5)
 (2, 4, 6)

然后,您可以在元组的转置数组(实际上是迭代器)上广播foo

julia> foo.(zip(args_array...)...)
(3, 7, 11)

但是,这将返回一个元组而不是一个数组。如果需要将返回值作为数组,则可以使用以下任何一种含糊的解决方案:

julia> foo.(collect.(zip(args_array...))...)
3-element Array{Int64,1}:
  3
  7
 11

julia> collect(foo.(zip(args_array...)...))
3-element Array{Int64,1}:
  3
  7
 11

julia> [foo.(zip(args_array...)...)...]
3-element Array{Int64,1}:
  3
  7
 11

答案 2 :(得分:0)

怎么样

[foo(x,y) for (x,y) in args_array]