如何高效将一维numpy零数组指定索引区间设为1(无循环)
高效实现一维NumPy数组的区间批量赋值
针对你需要给一维NumPy数组的多个索引区间批量设值的需求,这里提供两种无需for循环的高效方案,尤其适合大数量区间或大尺寸数组的场景:
方法一:差分累加(最优高效方案)
利用差分+前缀和的方式标记区间,完全基于NumPy向量化操作实现,时间复杂度仅为O(N)(N为数组长度),内存占用极低,是处理这类问题的最优选择。
实现代码:
import numpy as np indices_range_list = [(0,1), (3,8), (9,11)] my_array = np.zeros(15) # 拆分所有区间的起点和终点 starts, ends = zip(*indices_range_list) # 创建差分数组,标记区间的开始和结束 diff = np.zeros_like(my_array, dtype=int) np.add.at(diff, starts, 1) # 起点位置加1 np.add.at(diff, ends, -1) # 终点位置减1 # 计算前缀和,得到需要赋值的位置掩码 mask = diff.cumsum() > 0 # 批量赋值 my_array[mask] = 1 print(my_array)
输出结果:
array([1., 0., 0., 1., 1., 1., 1., 1., 0., 1., 1., 0., 0., 0., 0.])
原理说明:
- 差分数组通过
np.add.at批量标记每个区间的起点(+1)和终点(-1),避免循环操作 - 前缀和(
cumsum)后,区间内的位置会保持大于0的状态,区间外则归0,以此生成精准的赋值掩码 - 最后通过掩码批量赋值,全程无Python级循环,效率远高于for循环方案
方法二:生成所有索引赋值(适合小跨度区间)
如果你的区间跨度较小,可以直接生成所有需要赋值的索引,再批量赋值。但注意:当区间跨度极大时,该方法会生成庞大的索引数组,占用较多内存,效率不如差分法。
实现代码:
import numpy as np indices_range_list = [(0,1), (3,8), (9,11)] my_array = np.zeros(15) # 拼接所有区间的索引 indices = np.concatenate([np.arange(start, end) for start, end in indices_range_list]) # 批量赋值 my_array[indices] = 1 print(my_array)
输出结果:
array([1., 0., 0., 1., 1., 1., 1., 1., 0., 1., 1., 0., 0., 0., 0.])
方案对比
- 差分累加:无循环、内存占用低、效率稳定,无论区间数量多少都能保持高效,优先推荐
- 生成索引赋值:实现简单,但内存开销随区间跨度增大而增加,适合小跨度区间场景
- 原for循环:Python级循环在区间数量大时效率极低,不推荐用于大规模数据
内容的提问来源于stack exchange,提问作者StupendousMan
相关产品推荐
相关产品推荐

