寻求高效方法(如Numpy)统计二维数组中数字序列的出现次数
高效统计二维数组中目标序列的出现次数(NumPy方案)
嘿,这个问题我太熟悉了!三重循环确实能解决问题,但一旦数组规模变大,效率会直线下降。用NumPy的向量化操作可以轻松搞定,而且代码更简洁、速度快得多。
核心思路
对于二维数组中的每一个一维子数组,我们生成所有长度等于目标序列的滑动窗口,然后通过向量化比较统计每个子数组中匹配目标序列的窗口数量,最后累加所有子数组的结果即可。
实现代码
import numpy as np def count_seq_occ(target_seq, arr): target = np.array(target_seq) seq_length = len(target) total_matches = 0 for sub_array in arr: sub_len = len(sub_array) # 如果子数组长度小于目标序列,直接跳过 if sub_len < seq_length: continue # 生成滑动窗口视图(无数据复制,内存高效) sliding_windows = np.lib.stride_tricks.sliding_window_view(sub_array, seq_length) # 逐窗口比较是否与目标序列完全匹配,统计匹配数 matches = np.all(sliding_windows == target, axis=1).sum() total_matches += matches return total_matches # 测试你的示例 test_array = np.array([[2,3,5,2,3], [5,2,3], [1]]) print(count_seq_occ([2,3], test_array)) # 输出:3
为什么这个方案更优?
- 内存高效:
sliding_window_view不会复制原数组数据,只是创建一个视图,避免了额外的内存开销。 - 向量化加速:
np.all和sum都是NumPy优化过的向量化操作,比Python原生循环快几个数量级,尤其是当子数组长度较大时。 - 代码简洁:逻辑清晰,没有嵌套循环的冗余代码,可读性更强。
注意事项
- 需要NumPy版本≥1.20.0,因为
sliding_window_view是这个版本才新增的功能。如果你的版本较低,可以用as_strided手动实现滑动窗口,但代码会稍复杂一些。 - 子数组之间是独立统计的,不会跨子数组匹配序列(比如第一个子数组的最后一个元素和第二个子数组的第一个元素不会被当作连续序列),这符合你示例中的逻辑。
内容的提问来源于stack exchange,提问作者DsCpp
相关产品推荐
相关产品推荐

