You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

是否有Numpy函数可基于值而非索引在slice/range中筛选数组子集?

优化方案:用数值计算模拟range.__contains__逻辑

直接用NumPy的向量化数值运算替代range实例化,这是最高效的方案——完全利用NumPy底层优化,避免循环或生成大数组,完美匹配你想要的range.__contains__式的无实例化判断逻辑。

核心逻辑推导

range(r_start, r_stop, r_step)的元素必须满足三个条件:

  • 元素落在对应区间内(正步长时≥start且<stop,负步长时≤start且>stop)
  • (元素 - start) 能被step整除
  • 偏移量与步长的符号一致(保证元素在区间方向上,避免出现超出范围但刚好整除的情况)

实现代码

先对齐Python range的默认参数规则,再生成布尔掩码提取元素:

import numpy as np

def in_range(arr, start=0, stop=None, step=1):
    # 对齐Python range的默认参数逻辑
    if stop is None:
        start, stop = 0, start
    if step == 0:
        raise ValueError("step cannot be zero")
    
    arr = np.asarray(arr)
    # 第一步:判断元素是否在区间范围内
    if step > 0:
        range_cond = (arr >= start) & (arr < stop)
    else:
        range_cond = (arr <= start) & (arr > stop)
    # 第二步:判断元素是否符合步长间隔规则
    offset = arr - start
    step_cond = (offset % step == 0)
    # 补充符号判断,避免跨区间的整除值被误判
    if step > 0:
        step_cond &= (offset >= 0)
    else:
        step_cond &= (offset <= 0)
    
    # 合并条件并提取元素
    return arr[range_cond & step_cond]

为什么这比其他方案更优?

  • 碾压np.isin(arr, range(start, stop, step)):不用生成range对应的完整数组,内存占用近乎O(1),尤其当range跨度极大(比如range(0, 10**9, 2))时,彻底避免内存爆炸
  • 比np.vectorize/np.where结合range.__contains__快得多:np.vectorize本质是Python循环的包装,没有真正的向量化优化;而数值计算是纯NumPy底层C实现,速度差几个数量级

示例验证

arr = np.array([1,3,5,7,9,11,13])
# 提取range(3,12,2)的元素:3,5,7,9,11
print(in_range(arr, 3,12,2))  # 输出 [ 3  5  7  9 11]

# 负步长示例
arr = np.array([10,8,6,4,2,0])
print(in_range(arr, 10, 0, -2))  # 输出 [10  8  6  4  2]

额外适配:直接处理slice对象

如果你的输入是Python原生slice对象,先解析成start/stop/step再传入即可:

s = slice(3,12,2)
print(in_range(arr, s.start, s.stop, s.step))

内容的提问来源于stack exchange,提问作者bers

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 20:32:31