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

如何利用布尔掩码实现向量化方案,在大型二维NumPy数组中替换多组重复模式为更小的二维NumPy数组

向量化替换大型NumPy数组中的连续重复行模式

针对你需要处理百万行规模NumPy数组、批量替换连续重复行模式的需求,我整理了一套完全向量化的解决方案——全程依赖NumPy的C级运算,几乎没有Python层面的循环,能把性能损耗降到最低:

完整实现代码

import numpy as np

# 定义你的输入数组和替换模式
largeArr = np.array([
 [0, 1, 1],
 [0, 1, 1],
 [0, 1, 1],
 [0, 0, 0],
 [0, 0, 0],
 [0, 0, 0],
 [0, 1, 1],
 [0, 1, 1],
 [0, 1, 1],
 [0, 0, 0],
 [0, 0, 0],
 [3, 2, 0],
 [3, 2, 0],
 [3, 2, 0],
 [3, 2, 0],
 [0, 0, 0],
 [0, 0, 0],
 [3, 2, 0],
 [3, 2, 0],
 [3, 2, 0],
 [3, 2, 0],
 [0, 0, 0]
])

pattern1 = np.array([
 [0, 2, 1],
 [0, 2, 2],
 [0, 2, 3]
])
target1 = np.array([0, 1, 1])

pattern2 = np.array([
 [5, 2, 1],
 [5, 3, 2],
 [5, 4, 3],
 [5, 5, 4]
])
target2 = np.array([3, 2, 0])

def replace_consecutive_pattern(large_arr, target_row, replacement):
    # 第一步:标记每行是否完全匹配目标行
    row_matches = (large_arr == target_row).all(axis=1)
    n_replace_rows = replacement.shape[0]
    
    if n_replace_rows == 0:
        return large_arr
    
    # 第二步:用滑动窗口检测连续n_replace_rows个匹配行的起始位置
    # sliding_window_view创建原数组的视图,不复制数据,内存开销极小
    window_matches = np.lib.stride_tricks.sliding_window_view(row_matches, n_replace_rows).all(axis=1)
    
    # 获取所有符合条件的起始索引
    start_indices = np.where(window_matches)[0]
    
    # 可选:如果需要避免重叠替换(比如连续6行目标行只替换前3和后3,不重复替换中间)
    # 取消下面注释即可
    # if len(start_indices) > 0:
    #     keep = np.concatenate([[True], start_indices[1:] >= start_indices[:-1] + n_replace_rows])
    #     start_indices = start_indices[keep]
    
    # 第三步:批量替换对应区域
    for idx in start_indices:
        large_arr[idx:idx+n_replace_rows] = replacement
    
    return large_arr

# 依次应用替换规则(顺序会影响结果,按你的需求顺序执行)
result = replace_consecutive_pattern(largeArr.copy(), target1, pattern1)
result = replace_consecutive_pattern(result, target2, pattern2)

# 验证结果是否符合预期
expected = np.array([
 [0, 2, 1], [0, 2, 2], [0, 2, 3],
 [0, 0, 0], [0, 0, 0], [0, 0, 0],
 [0, 2, 1], [0, 2, 2], [0, 2, 3],
 [0, 0, 0], [0, 0, 0],
 [5, 2, 1], [5, 3, 2], [5, 4, 3], [5, 5, 4],
 [0, 0, 0], [0, 0, 0],
 [5, 2, 1], [5, 3, 2], [5, 4, 3], [5, 5, 4],
 [0, 0, 0]
])

print(np.array_equal(result, expected))  # 输出 True

核心逻辑拆解

  1. 行匹配掩码:(large_arr == target_row).all(axis=1)生成布尔数组,快速标记每一行是否和目标行完全一致——这一步是向量化的,处理百万行也能瞬间完成。
  2. 滑动窗口检测连续匹配:np.lib.stride_tricks.sliding_window_view创建窗口大小等于替换模式行数的滑动视图,然后检查每个窗口内是否全为True,精准定位连续重复目标行的起始位置。
  3. 批量赋值替换:直接通过NumPy切片赋值,把替换模式写入对应区域——切片赋值是底层优化的操作,比逐行循环快几个数量级。

性能优化点

  • 全程使用NumPy内置的向量化操作,避免Python循环的开销。
  • sliding_window_view不复制原数组,只创建视图,内存占用极低,适合超大型数组。
  • 如果需要处理多组替换规则,只需按顺序调用函数即可,每一步都是独立的向量化操作。

可选调整:避免重叠替换

如果你的数组中存在连续超过N次的目标行(比如连续6行[0,1,1]),默认代码会替换成两个独立的pattern1(0-2行和3-5行)。如果想避免这种重叠检测(比如只替换0-2行,跳过3-5行),可以取消函数中对应注释的代码,过滤掉间隔小于替换行数的起始索引。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 17:17:29