能否将NumPy非反对角线花式索引转换为基础切片索引?
解决方案
可以通过NumPy的 stride 技巧实现,得到的结果是原数组的视图(不复制数据),且内存不连续,同时代码可读性较好。
实现代码
import numpy as np source = np.arange(400).reshape(20, 20) # 计算目标序列的步长:每次向下移动1行、向左移动1列,步长为行步长减去列步长 step_stride = source.strides[0] - source.strides[1] # 从起始点(0,18)开始,按指定步长取10个元素 target = np.lib.stride_tricks.as_strided(source[0, 18], shape=(10,), strides=(step_stride,))
说明
- 视图特性:
as_strided直接基于原数组的内存缓冲区创建视图,不复制任何数据,和原数组共享内存。 - 内存不连续:原数组是C连续的(行优先),而目标序列的步长是
行步长 - 列步长(例如int64类型下为160-8=152字节),不是单个元素字节数的整数倍,因此内存布局不连续。 - 结果匹配:该方法获取的元素和原花式索引完全一致,可以通过以下代码验证:
# 原花式索引的结果 fancy_indices = np.arange(10), 18 - np.arange(10) original_target = source[fancy_indices] # 验证两个数组完全相等 print(np.array_equal(target, original_target)) # 输出 True # 验证target是视图(修改原数组会同步改变target) source[0,18] = 999 print(target[0]) # 输出 999
可读性优化
如果觉得as_strided的写法不够直观,可以加注释说明逻辑,或者封装成一个简单函数:
def get_offset_diagonal_view(arr, start_row, start_col, length, step_row=1, step_col=-1): """获取数组中指定起始点、步长的对角线索引视图""" stride = arr.strides[0] * step_row + arr.strides[1] * step_col return np.lib.stride_tricks.as_strided(arr[start_row, start_col], shape=(length,), strides=(stride,)) # 调用示例 target = get_offset_diagonal_view(source, start_row=0, start_col=18, length=10)
内容的提问来源于stack exchange,提问作者feiyang472
相关产品推荐
相关产品推荐

