如何无循环实现连续零组合统计并提升代码运行效率?
提取列表中连续目标值的长度列表
问题说明
给定一个仅包含两种不同值的列表(示例用0和1,实际场景为字符串值),需要生成连续“目标值”(示例中为0)的长度列表(即“连续目标值组合”)。例如输入[0, 1, 1, 0, 0, 0, 1, 0, 0,],结果应为[1, 3, 2]。
已实现的循环版本
本人已写出循环实现的代码,逻辑清晰但在大数据量下速度偏慢:
data = [0, 1, 1, 0, 0, 0, 1, 0, 0,] zeros_combo = [] count_zeros = 0 for value in data: if value == 0: count_zeros += 1 else: # 遇到非目标值时,若之前有计数则存入结果并重置 if count_zeros > 0: zeros_combo.append(count_zeros) count_zeros = 0 # 处理列表末尾的连续目标值 if count_zeros > 0: zeros_combo.append(count_zeros) print(zeros_combo) # 输出: [1, 3, 2]
需求:无循环的优化方案
希望找到无需显式循环的优化实现,比如利用pandas、numpy等库的向量化函数提升速度,因为循环迭代和逐元素对比的效率在数据量大时表现不佳。
已尝试的低效方法
本人试过以下多种方法,但运行速度均不如原循环版本,甚至更慢:
字符串拼接分割法
res = [v for v in map(len, ''.join(map(str, data)).split('1')) if v != 0]
res = list(filter(lambda v: v != 0, map(len, ''.join(map(str, data)).split('1'))))
正则表达式匹配法
import re res = list(map(len, re.findall(r'0+', ''.join(map(str, data)))))
itertools.groupby分组法
from itertools import groupby res = [len(list(g)) for k, g in groupby(data, lambda x: x==0) if k]
pandas分组聚合(速度极慢)
import pandas as pd s = pd.Series(data) res = s[s==0].groupby(s.diff().ne(0).cumsum()).agg(len).values
推荐的numpy向量化优化方案
对于大数据量场景,numpy的向量化操作能显著提升效率,以下是实现代码:
import numpy as np data = np.array([0, 1, 1, 0, 0, 0, 1, 0, 0,]) # 生成标记数组:目标值为1,非目标值为0 mask = data == 0 # 计算连续目标值的边界:开头加0,结尾加0,方便检测起始和结束点 pad_mask = np.concatenate([[0], mask, [0]]) # 找到边界变化的索引:从0变1是连续目标值的开始,从1变0是结束 changes = np.where(pad_mask != np.roll(pad_mask, 1))[0] # 计算每段连续目标值的长度 res = changes[1::2] - changes[::2] print(res.tolist()) # 输出: [1, 3, 2]
该方法通过numpy的数组操作替代循环,在数据量越大时,性能优势越明显。
内容的提问来源于stack exchange,提问作者Misha
相关产品推荐
相关产品推荐

