如何在rust-ndarray中对非连续视图执行轴拆分式重塑?
问题分析
你的代码报错是因为b是非连续视图:原数组a每行有10个元素,b取每行前8个,导致行与行之间的内存间隔是10而非8,整体内存布局不连续。ndarray的into_shape对视图的要求严格,仅允许不改变内存布局的重塑操作,而NumPy的reshape会自动适配非连续数组(通过调整步长或按需复制),因此两者表现不同。
解决方案
方案1:转为连续数组后重塑(简单安全,允许复制)
这是最直接的处理方式:先将非连续视图复制为拥有所有权的连续数组,再执行重塑操作。
use ndarray::prelude::*; fn main() { let a = Array2::<i32>::zeros([100, 10]); let b = a.slice(s![5..15, ..8]); // to_owned() 复制非连续视图为连续数组 let c = b.to_owned().into_shape((10, 2, 4)).expect("shape mismatch"); dbg!(c); }
方案2:轴迭代拆分(按需复制,避免全量复制)
如果不想一次性复制整个视图,可以对每行(每行本身是连续的)单独拆分,再组合成三维数组:
use ndarray::prelude::*; fn main() { let a = Array2::<i32>::zeros([100, 10]); let b = a.slice(s![5..15, ..8]); // 遍历每行(连续)并拆分,最终收集为三维数组 let c = b.axis_iter(Axis(0)) .map(|row| row.into_shape((2, 4)).unwrap()) .collect::<Array3<_>>(); dbg!(c); }
方案3:unsafe手动构造视图(无复制,需谨慎)
如果完全不想复制内存,可以通过unsafe代码手动构造符合步长要求的三维视图,前提是你明确内存布局的安全性:
use ndarray::prelude::*; fn main() { let a = Array2::<i32>::zeros([100, 10]); let b = a.slice(s![5..15, ..8]); unsafe { // 指定形状、数据指针和步长(单位:字节) let c = ArrayView3::from_shape_ptr( (10, 2, 4), b.as_ptr(), (10 * std::mem::size_of::<i32>(), 4 * std::mem::size_of::<i32>(), std::mem::size_of::<i32>()), ); dbg!(c); } }
内容的提问来源于stack exchange,提问作者Jason Orendorff
相关产品推荐
相关产品推荐

