将二维元组添加到 Julia 中的二维数组

Add 2d tuple to a 2d array in Julia

如何在 Julia 中将二维元组添加到二维矩阵?

    t1 = ((10,20),(30,40)); #2d immutable tuple 
    a = [1 2;3 4] #2d matrix 
    a .+ t1 

抛出错误:

MethodError: no method matching +(::Int64, ::Tuple{Int64, Int64})
Closest candidates are:
  +(::Any, ::Any, ::Any, ::Any...) at operators.jl:560
  +(::T, ::T) where T<:Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8} at int.jl:87
  +(::Integer, ::Ptr) at pointer.jl:161
  ...
Stacktrace:
 [1] _broadcast_getindex_evalf
   @ .\broadcast.jl:648 [inlined]
 [2] _broadcast_getindex
   @ .\broadcast.jl:621 [inlined]
 [3] getindex
   @ .\broadcast.jl:575 [inlined]
 [4] copy
   @ .\broadcast.jl:922 [inlined]
 [5] materialize(bc::Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{2}, Nothing, typeof(+), Tuple{Matrix{Int64}, Tuple{Tuple{Int64, Int64}, Tuple{Int64, Int64}}}})
   @ Base.Broadcast .\broadcast.jl:883
 [6] top-level scope
   @ REPL[15]:1

有vector/matrix加法吗? 显然我可以使用 for 循环逐个元素添加。

啊,所以这里的问题是,当你称 t1 为“二维元组”时,它实际上不是;它是一个嵌套的元组,一个 元组中的元组 ,因此与你的二维数组(实际上 一个双 -维度对象,而不仅仅是数组的数组)。

如果要将二维数组添加到可以像 Tuple 一样堆栈分配的不可变对象,同时是真正的二维,那么您可以使用 StaticArrays.jl 包,它提供了不可变的 SArray 类型:

julia> a = [1 2; 3 4]
2×2 Matrix{Int64}:
 1  2
 3  4

julia> using StaticArrays

julia> t1 = SA[10 20; 30 40]
2×2 SMatrix{2, 2, Int64, 4} with indices SOneTo(2)×SOneTo(2):
 10  20
 30  40

julia> a + t1
2×2 SMatrix{2, 2, Int64, 4} with indices SOneTo(2)×SOneTo(2):
 11  22
 33  44

但是,如果出于任何原因您真的想坚持使用 嵌套 而不是多维,那么让我们也使数组嵌套

julia> t1 = ((10,20),(30,40)) #tuple-of-tuples
((10, 20), (30, 40))

julia> a = [[1,2],[3,4]] #vector-of-vectors
2-element Vector{Vector{Int64}}:
 [1, 2]
 [3, 4]

在这种情况下你可以通过递归轻松解决

add(a,b) = a + b
add(a::Vector, b::NTuple{N}) where N = [add(a[i],b[i]) for i in 1:N]
add(a::NTuple{N}, b::Vector) where N = [add(a[i],b[i]) for i in 1:N]
julia> add(a,t1)
2-element Vector{Vector{Int64}}:
 [11, 22]
 [33, 44]

这种方法也适用于任意深度嵌套的对象:

julia> a = [[[1,2],[3,4]],[[5,6],[7,8]]]
2-element Vector{Vector{Vector{Int64}}}:
 [[1, 2], [3, 4]]
 [[5, 6], [7, 8]]

julia> t1 = (((10,20),(30,40)),((50,60),(70,80)))
(((10, 20), (30, 40)), ((50, 60), (70, 80)))

julia> add(a,t1)
2-element Vector{Vector{Vector{Int64}}}:
 [[11, 22], [33, 44]]
 [[55, 66], [77, 88]]

不幸的是,真正的多维数组与在不支持真正的多维数组的语言中使用向量向量的常见技巧之间存在广泛的语义混淆。

@cbk 已经解释了嵌套数组如何不等同于多维结构。但是,如果您的结构已经嵌套,您当然可以将添加编写为嵌套广播。自(我相信)Julia 1.6 以来,有独立“广播运算符”的语法,这是可能的:

julia> t1 = ((10,20),(30,40))
((10, 20), (30, 40))

julia> a = [[1,2],[3,4]]
2-element Vector{Vector{Int64}}:
 [1, 2]
 [3, 4]

julia> broadcast(.+, a, t1)
2-element Vector{Vector{Int64}}:
 [11, 22]
 [33, 44]

如果 aMatrix,您可以在 eachrow 上执行相同的操作:

julia> a = [1 2;3 4]
2×2 Matrix{Int64}:
 1  2
 3  4

julia> broadcast(.+, eachrow(a), t1)
2-element Vector{Vector{Int64}}:
 [11, 22]
 [33, 44]

(在此特定情况下,map 等同于 broadcast。)