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

Python递归按时间区间拆分列表报递归深度超限如何修复

问题说明

场景说明

业务逻辑为采集用户观看拼接长视频的按键行为:用户每次按键时,记录当前视频播放位置的毫秒级时间戳存入列表。该长视频由多个时长20-60秒的独立试次(trial)视频拼接而成,系统无法识别试次边界,需根据已知参数拆分时间戳列表:

  • trials_num:试次总数量,即最终输出的子列表总个数
  • trial_length:单个试次时长(单位:秒),转换为毫秒后作为区间步长,时间区间依次为0~trial_length*1000ms、trial_length*1000+1~2*trial_length*1000ms……以此类推,每个区间内的时间戳归入对应子列表,单个试次对应的时间戳数量无固定要求。

现有代码与问题

编写的递归函数break_lists代码如下:

def break_lists(orig_list, trial_length, trials_num, final_list):
    # 生成对应试次数量的遍历序列
    t = []
    for num in range(1, trials_num + 1):
        t.append(num)
    # 秒转毫秒计算单试次时长
    ms_length = trial_length * 1000
    # 遍历所有试次
    for num in t:
        sublist = []
        # 遍历列表前40个元素(单试次最多40个时间戳)
        for i in range(0, 40):
            if orig_list[i] <= ms_length * num:
                sublist.append(orig_list[i])
            else:
                # 超出当前区间则递归处理剩余列表
                break_lists(orig_list[i:], trial_length, trials_num, final_list)
        
        final_list.append(sublist)
    print(final_list)
    return(final_list)

测试用例:

  • 输入时间戳列表:[2000, 3000, 4000, 5000, 6000, 7000, 9000, 12000, 15000, 17000, 19000, 80000]
  • 调用方式:break_lists(list, 5, 20, [])
  • 预期输出:[[2000, 3000, 4000, 5000], [6000, 7000, 9000], [12000, 15000], [17000, 19000], [80000]]

运行代码时触发maximum recursion depth exceeded in comparison报错,调整代码后偶尔可运行,但会生成大量超出试次数量的多余空子列表,无法得到预期结果。

问题根因

原代码存在3个核心bug:

  1. 递归逻辑完全失控:每次进入递归都会重新遍历全部trials_num个试次,没有记录当前处理到的试次序号,递归层数无限制增长直接触发栈溢出
  2. 硬编码单试次最多40个时间戳:单试次时间戳超过40个会触发索引越界,不足40个同样会报索引错误
  3. 没有列表切分标记:每次都是从传入列表的头部开始判断,不会移动处理位置,重复生成大量空的子列表
修复方案

这个场景完全不需要用递归,用移动指针顺序遍历的方式实现逻辑更简单,也不会有栈溢出问题:

def break_lists(orig_list, trial_length, trials_num):
    ms_length = trial_length * 1000
    final_list = []
    # ptr标记当前处理到原列表的位置
    ptr = 0
    total_ts = len(orig_list)
    # 逐试次匹配时间区间
    for trial_idx in range(1, trials_num + 1):
        upper_bound = ms_length * trial_idx
        sublist = []
        # 从当前指针位置向后找,所有落在当前区间的时间戳都归入子列表
        while ptr < total_ts and orig_list[ptr] <= upper_bound:
            sublist.append(orig_list[ptr])
            ptr += 1
        # 非空子列表才加入结果,不需要多余空列表
        if sublist:
            final_list.append(sublist)
        # 所有时间戳处理完直接退出,不用遍历剩余空试次
        if ptr >= total_ts:
            break
    return final_list

测试验证

用给出的测试用例调用:

test_ts = [2000, 3000, 4000, 5000, 6000, 7000, 9000, 12000, 15000, 17000, 19000, 80000]
print(break_lists(test_ts, 5, 20))

输出完全匹配预期:
[[2000, 3000, 4000, 5000], [6000, 7000, 9000], [12000, 15000], [17000, 19000], [80000]]

补充说明:如果业务要求最终输出子列表数量必须严格等于trials_num(即使后续试次无按键也要保留空列表),去掉sublist非空判断和提前退出的break逻辑即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 02:45:47