假设我有这个矩阵:
julia> mat = [
1 2 3 4
5 6 7 8
9 8 7 6
];
然后我想把这个矩阵的切片放入具有SMatrix{Int64}
类型的3DArray
中,如下所示:
julia> using StaticArrays
julia> arr = Array{SMatrix{Int64}, 3}(undef, 3, 2, 3);
julia> col_idx = [1, 2, 3];
julia> foreach(x->arr[:, :, x] = mat[:, x:x+1], col_idx)
ERROR: MethodError: Cannot `convert` an object of type
Int64 to an object of type
SMatrix{Int64}
Closest candidates are:
convert(::Type{T}, ::LinearAlgebra.Factorization) where T<:AbstractArray at C:UsersJUL.juliajuliaupjulia-1.8.3+0.x64sharejuliastdlibv1.8LinearAlgebrasrcfactorization.jl:58
convert(::Type{SA}, ::Tuple) where SA<:StaticArray at C:UsersJUL.juliapackagesStaticArraysx7lS0srcconvert.jl:179
convert(::Type{SA}, ::SA) where SA<:StaticArray at C:UsersJUL.juliapackagesStaticArraysx7lS0srcconvert.jl:178
...
Stacktrace:
[1] setindex!
@ .array.jl:968 [inlined]
[2] macro expansion
@ .multidimensional.jl:946 [inlined]
[3] macro expansion
@ .cartesian.jl:64 [inlined]
[4] macro expansion
@ .multidimensional.jl:941 [inlined]
[5] _unsafe_setindex!(::IndexLinear, ::Array{SMatrix{Int64}, 3}, ::Matrix{Int64}, ::Base.Slice{Base.OneTo{Int64}}, ::Base.Slice{Base.OneTo{Int64}}, ::Int64)
@ Base .multidimensional.jl:953
[6] _setindex!
@ .multidimensional.jl:930 [inlined]
[7] setindex!(::Array{SMatrix{Int64}, 3}, ::Matrix{Int64}, ::Function, ::Function, ::Int64)
@ Base .abstractarray.jl:1344
[8] (::var"#5#6")(x::Int64)
@ Main .REPL[20]:1
[9] foreach(f::var"#5#6", itr::Vector{Int64})
@ Base .abstractarray.jl:2774
[10] top-level scope
@ REPL[20]:1
我怎样才能实现它?
注::
这只是一个最小的和可复制的例子。在实际意义上,我对arr
有一个(10, 10, 2000)
的大小,对mat
也有一个大的大小(10x2000
,我猜)!
如果我理解正确,你想要一个数组的SMatrices吗?
mat = [ 1 2 3 4
5 6 7 8
9 8 7 6 ];
using StaticArrays
col_idx = [1, 2, 3];
arr = [SMatrix{3,2}(mat[:, x:x+1]) for x in col_idx]
3-element Vector{SMatrix{3, 2, Int64, 6}}:
[1 2; 5 6; 9 8]
[2 3; 6 7; 8 7]
[3 4; 7 8; 7 6]
那么,如果我说:
julia> using StaticArrays
julia> mat = [
1 2 3 4
5 6 7 8
9 8 7 6
];
julia> arr = Array{Int64, 3}(undef, 3, 2, 3);
julia> foreach(x->arr[:, :, x] = mat[:, x:x+1], [1, 2, 3]);
julia> sarr = SArray{Tuple{3, 2, 3}}(arr)
3×2×3 SArray{Tuple{3, 2, 3}, Int64, 3, 18} with indices SOneTo(3)×SOneTo(2)×SOneTo(3):
[:, :, 1] =
1 2
5 6
9 8
[:, :, 2] =
2 3
6 7
8 7
[:, :, 3] =
3 4
7 8
7 6
julia> typeof(sarr[:, :, 1])
SMatrix{3, 2, Int64, 6} (alias for SArray{Tuple{3, 2}, Int64, 2, 6})
首先,我创建了一个常规的3DArray
,然后在此基础上构建了一个SArray
。然而,考虑到你的实际情况,我尝试了以下方法:
julia> mat = rand(10, 2000);
julia> arr = Array{Float64, 3}(undef, 10, 2, 1999);
julia> foreach(x->arr[:, :, x] = mat[:, x:x+1], 1:1999);
julia> sarr = SArray{Tuple{10, 2, 1999}}(arr);
但是构造这样的容器需要花费太多的时间。(我已经取消了,我不知道它的运行时间。)因此,在这些情况下,最好采纳@AboAmmar的建议。
受@Shayan和@AboAmmar的启发,这个答案探讨了使用BlockArrays.jl
包来构建期望的结果。BlockArrays
将现有数组放入'元数组'。子数组可以是SMatrix类型。
在代码:
using StaticArrays, BlockArrays
mat = rand(10,2000) # random demo matrix
# make all the slice SArrays
arr = [SArray{Tuple{10,2,1}, Float64, 3}(mat[:,i:i+1])
for i=1:1999]
arr = reshape(arr,1,1,1999)
# glue them into a BlockArray
bricked = mortar(arr)
现在后:
julia> size(bricked)
(10, 2, 1999)
julia> bricked[:,:,25]
1×1-blocked 10×2 BlockMatrix{Float64}:
0.265972 0.258414
0.396142 0.863366
0.41708 0.648276
0.960283 0.773064
0.62513 0.268989
0.132796 0.0493077
0.844674 0.791772
0.59638 0.0769661
0.221536 0.388623
0.595742 0.50732
希望这个方法能得到你想要的性能折衷(或者至少引入一些新的想法)。