将 Array{T,N} 转换为 Array{Array{T,M},N-M} 的优雅方式
Elegant way to turn a Array{T,N} to a Array{Array{T,M},N-M}
假设我开始于:
x = collect(reshape(1:24, (3,4,2)))
3×4×2 Array{Int64,3}:
[:, :, 1] =
1 4 7 10
2 5 8 11
3 6 9 12
[:, :, 2] =
13 16 19 22
14 17 20 23
15 18 21 24
我想讲这个:
3×2 Array{Array{Int64,1},2}:
[1, 4, 7, 10] [13, 16, 19, 22]
[2, 5, 8, 11] [14, 17, 20, 23]
[3, 6, 9, 12] [15, 18, 21, 24]
这有点像 eachslice
所做的,除了我需要遍历不止一个维度。到目前为止,我可以通过广播 getindex
和非常笨拙的轴重塑来为这个特定的数组完成此操作:
y = getindex.(Ref(x), axes(x,1), Ref(:),
reshape(axes(x,3), 1, length(axes(x,3)) )
)
但是针对不同的阵形进行调整显然是非常麻烦的。主要的挂断是必须重塑轴的形状以进行广播,它不像 getindex(x,:,1,:)
那样干净,其中轴被假定为正交。
除了已经讨论过的解决方案之外,还可以使用 mapslices
:
来实现
julia> mapslices(a -> [a], x; dims=(2,))
3×1×2 Array{Vector{Int64}, 3}:
[:, :, 1] =
[1, 4, 7, 10]
[2, 5, 8, 11]
[3, 6, 9, 12]
[:, :, 2] =
[13, 16, 19, 22]
[14, 17, 20, 23]
[15, 18, 21, 24]
在这种情况下,结果是一个 3x1x2
数组,但我们可以轻松创建一个函数,它也删除单例维度:
reslice(a, dims) = dropdims(mapslices(x -> [x], x; dims); dims)
julia> reslice(x, (2,))
3×2 Matrix{Vector{Int64}}:
[1, 4, 7, 10] [13, 16, 19, 22]
[2, 5, 8, 11] [14, 17, 20, 23]
[3, 6, 9, 12] [15, 18, 21, 24]
此解决方案不如“getindex
”解决方案有效,但可能更能抓住意图。
假设我开始于:
x = collect(reshape(1:24, (3,4,2)))
3×4×2 Array{Int64,3}:
[:, :, 1] =
1 4 7 10
2 5 8 11
3 6 9 12
[:, :, 2] =
13 16 19 22
14 17 20 23
15 18 21 24
我想讲这个:
3×2 Array{Array{Int64,1},2}:
[1, 4, 7, 10] [13, 16, 19, 22]
[2, 5, 8, 11] [14, 17, 20, 23]
[3, 6, 9, 12] [15, 18, 21, 24]
这有点像 eachslice
所做的,除了我需要遍历不止一个维度。到目前为止,我可以通过广播 getindex
和非常笨拙的轴重塑来为这个特定的数组完成此操作:
y = getindex.(Ref(x), axes(x,1), Ref(:),
reshape(axes(x,3), 1, length(axes(x,3)) )
)
但是针对不同的阵形进行调整显然是非常麻烦的。主要的挂断是必须重塑轴的形状以进行广播,它不像 getindex(x,:,1,:)
那样干净,其中轴被假定为正交。
除了已经讨论过的解决方案之外,还可以使用 mapslices
:
julia> mapslices(a -> [a], x; dims=(2,))
3×1×2 Array{Vector{Int64}, 3}:
[:, :, 1] =
[1, 4, 7, 10]
[2, 5, 8, 11]
[3, 6, 9, 12]
[:, :, 2] =
[13, 16, 19, 22]
[14, 17, 20, 23]
[15, 18, 21, 24]
在这种情况下,结果是一个 3x1x2
数组,但我们可以轻松创建一个函数,它也删除单例维度:
reslice(a, dims) = dropdims(mapslices(x -> [x], x; dims); dims)
julia> reslice(x, (2,))
3×2 Matrix{Vector{Int64}}:
[1, 4, 7, 10] [13, 16, 19, 22]
[2, 5, 8, 11] [14, 17, 20, 23]
[3, 6, 9, 12] [15, 18, 21, 24]
此解决方案不如“getindex
”解决方案有效,但可能更能抓住意图。