multidimensional-array - 将 Array{T,N} 转换为 Array{Array{T,M},N-M} 的优雅方法

标签 multidimensional-array indexing julia array-broadcasting

假设我从以下内容开始:

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 的作用,只不过我需要迭代超过 1 个维度。到目前为止,我可以通过广播 getindex 和非常尴尬的轴 reshape 来完成此特定数组的操作:

y = getindex.(Ref(x), axes(x,1), Ref(:),
                      reshape(axes(x,3), 1, length(axes(x,3)) )
              )

但是针对不同的数组形状进行调整显然是非常麻烦的。主要的问题是必须 reshape 轴的形状以进行广播,它不像 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”解决方案高效,但可以更好地捕捉意图。

关于multidimensional-array - 将 Array{T,N} 转换为 Array{Array{T,M},N-M} 的优雅方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69187478/

相关文章:

Python:迭代数组的行和列

sql - 具有时间有效性的 Oracle 表的主键违规

sql - 同一列上的聚集索引和非聚集索引有什么用

programming-languages - 我需要学习什么才能为编程语言做出贡献?

julia - 将 Array{Int64} 转换为 Array{Int32} 时检查溢出的方法

performance - 在 Julia 中更快地读取 CSV 文件

php - 在嵌套数组中搜索值

c - 为什么 `*(multi + row)` 生成指针地址而不是值?

javascript - Vue.js 从数组中弹出一个嵌套对象

r - 将向量转换为 data.frame,每个唯一值对应一列