如何让Julia中数组的view返回无单维度的低秩向量/子数组?
问题描述
我尝试从N维数组中获取切片/子数组,这些切片本质是已知长度的向量,通用情况下是秩M<N的数组(维度已知)。我希望将这些切片作为参数传入接受秩M的Array或Vec的函数,而非带大量单维度的Array(即Vec而非尺寸为(n,1,1,...)的Array{N})。例如,我希望view(A,indx...)返回秩1、尺寸为(n,)的引用(如SubArray),而非秩M且尺寸为(n,1,1,...)的对象。我理解view为了类型稳定会保留原数组类型,但我不想修改函数以适配带单维度的参数,同时也不想通过定义新数组并使用setindex!的方式(这几乎肯定更慢)。
解决方案
1. 使用selectdim直接生成低秩视图
selectdim是Julia内置函数,专门用于提取数组指定维度的切片,并且会自动移除单维度,返回对应秩的SubArray(无需复制数据)。
示例:
- 从3维数组中提取第2维度的第3个切片,得到2维SubArray:
A = rand(3, 4, 5) slice = selectdim(A, 2, 3) # 返回尺寸为(3,5)的SubArray,而非(3,1,5)
- 链式调用提取多维度切片,得到1维SubArray:
slice = selectdim(selectdim(A, 3, 4), 2, 3) # 返回尺寸为(3,)的SubArray
2. 结合@view与dropdims移除单维度
dropdims可以移除数组中尺寸为1的维度,配合@view可以生成视图而非复制数组。既可以手动指定要移除的维度,也能自动查找所有单维度:
示例:
A = rand(3, 4, 5) # 手动指定要移除的维度 slice = @view dropdims(A[:, 3, 4], dims=(2, 3)) # 返回尺寸为(3,)的SubArray # 自动查找所有单维度并移除 v = view(A, :, 3, 4) slice = @view dropdims(v, dims=findall(d -> size(v, d) == 1, 1:ndims(v)))
3. 自定义工具函数简化调用
如果需要频繁处理这类切片,可以写一个自定义函数,自动处理索引并生成低秩视图:
function sliceview(A, inds...) # 生成原始视图 v = view(A, inds...) # 找出所有尺寸为1的维度 single_dims = findall(d -> size(v, d) == 1, 1:ndims(v)) # 返回移除单维度后的视图 isempty(single_dims) ? v : @view dropdims(v, dims=single_dims) end
调用示例:
slice = sliceview(A, :, 3, 4) # 直接返回尺寸为(3,)的SubArray
注意事项
- 类型稳定性:如果目标函数要求固定秩的输入,优先使用
selectdim,它的返回秩可静态推断(N减去指定的维度数量);自动查找单维度的方式可能带来类型不稳定,更适合动态场景。 - 性能:上述方法均基于视图(SubArray),不会复制原数组数据,性能与
view相当。
内容的提问来源于stack exchange,提问作者TheWhitestOfFangs
相关产品推荐
相关产品推荐

