如何用简化版RLE快速压缩NumPy中的0-1一维数组?
用NumPy高效实现0/1数组的游程编码(RLE)
针对0/1组成的一维NumPy数组,用NumPy的向量化操作可以彻底替代慢的Python循环,核心思路是通过找元素变化的分界点来计算每个游程的长度,具体步骤如下:
核心实现逻辑
- 定位游程分界点:用
np.diff计算相邻元素的差值,0/1数组中差值不为0的位置就是前后游程的分界处,再把索引调整为原数组的位置。 - 计算游程长度:把分界点前后补上数组的起始(0)和结束(数组长度)位置,再用
np.diff计算相邻分界点的距离,得到每个游程的长度。 - 格式转换:把长度数组转成字符串拼接,得到你需要的连续数字格式(比如示例中的
433121)。
完整代码示例
import numpy as np def rle_binary_numpy(arr): # 输入合法性校验 if arr.ndim != 1 or not np.all(np.isin(arr, [0, 1])): raise ValueError("输入必须是仅包含0和1的一维NumPy数组") # 找到元素发生变化的索引位置 diffs = np.diff(arr) change_indices = np.where(diffs != 0)[0] + 1 # 转换为原数组的索引 # 计算每个游程的长度 run_bounds = np.concatenate(([0], change_indices, [len(arr)])) run_lengths = np.diff(run_bounds) # 转换为要求的连续数字字符串 return ''.join(map(str, run_lengths)) # 测试你的示例输入 test_array = np.array([0,0,0,0,1,1,1,0,0,0,1,0,0,1]) print(rle_binary_numpy(test_array)) # 输出: 433121
为什么比for循环快?
NumPy的所有核心操作(diff/where/concatenate)都是底层用C实现的向量化运算,完全避开了Python解释器的循环开销。当数组规模较大(比如百万级元素)时,速度会比Python循环快几个数量级。
边界情况测试
- 全0数组:
np.array([0,0,0])→ 返回'3' - 全1数组:
np.array([1,1,1,1])→ 返回'4' - 单元素数组:
np.array([0])→ 返回'1'
内容的提问来源于stack exchange,提问作者amit
相关产品推荐
相关产品推荐

