在不同大小的阵列上广播

Broadcasting over different sized arrays

假设我有以下功能

function foo(p :: Int, x :: Real)
  return p*x
end

我想为以下数组调用它:

P = [1, 2, 3]
X = [5.0, 6.0, 7.0, 8.0]

如果我想调用 foo 并将值存储在大小为 (length(P), length(X)) 的单个数组中,我可以将 XP 双重循环为:

R = zeros(length(P), length(X))
for i in 1:length(P), j in 1:length(X)
  R[i, j] = foo(P[i], X[j])
end

但是,有没有另一种方法可以做到这一点,同时明确避免双重循环? 也许是这样的?

R = foo.(collect(zip(P, X)))

当然,上述方法不起作用,因为 foo 无法处理 ::Tuple{Int64, Float64},但目前我还没有找到一种方法来广播不同大小的数组。任何提示将不胜感激,谢谢!

如果你想使用广播,你可以这样做:

julia> foo.(P, permutedims(X))
3×4 Matrix{Float64}:
  5.0   6.0   7.0   8.0
 10.0  12.0  14.0  16.0
 15.0  18.0  21.0  24.0

julia> foo.(P, reshape(X, 1, :))
3×4 Matrix{Float64}:
  5.0   6.0   7.0   8.0
 10.0  12.0  14.0  16.0
 15.0  18.0  21.0  24.0

julia> (((x, y),) -> foo(x, y)).(Iterators.product(P, X))
3×4 Matrix{Float64}:
  5.0   6.0   7.0   8.0
 10.0  12.0  14.0  16.0
 15.0  18.0  21.0  24.0

julia> Base.splat(foo).(Iterators.product(P, X))
3×4 Matrix{Float64}:
  5.0   6.0   7.0   8.0
 10.0  12.0  14.0  16.0
 15.0  18.0  21.0  24.0

请注意,伴随 (') 通常不会在这里工作,因为它是递归的:

julia> x = ["a", "b"]
2-element Vector{String}:
 "a"
 "b"

julia> permutedims(x)
1×2 Matrix{String}:
 "a"  "b"

julia> x'
1×2 adjoint(::Vector{String}) with eltype Union{}:
Error showing value of type LinearAlgebra.Adjoint{Union{}, Vector{String}}:
ERROR: MethodError: no method matching adjoint(::String)