滑动窗口场景列表推导式问题:结果为空、运行缓慢原因解析
滑动窗口代码改写问题解答
问题场景
我在滑动窗口项目中编写了一段可正常运行的代码:
# aby是一维列表,示例:[0.010,0.012,0.008,......,0.009] adj_qth_amp = 100 scan_window_size = 10000 wanted_time_stamps = [] window_sum = sum(aby[:scan_window_size]) for i in range(len(aby)-scan_window_size): window_sum = window_sum - aby[i] + aby[scan_window_size+i] if window_sum > adj_qth_amp: wanted_time_stamps.append(i) # 运行时间4分钟 # 执行后返回包含有效元素的wanted_time_stamps列表
这段代码耗时4分钟,能返回正确结果。随后我尝试用列表推导式改写,代码如下:
wanted_time_stamps = [(window_sum - aby[i] + aby[scan_window_size+i]) for i in range(len(aby)-scan_window_size) if (window_sum - aby[i] + aby[scan_window_size+i]) > adj_qth_amp] # 运行时间8分钟 # 执行后返回空列表(如[])
但改写后的代码不仅耗时翻倍,还返回空列表。我的问题:
- 第二种方法返回空列表的原因是什么?
- 为何第二种方法的运行时间约为第一种的两倍?列表推导式不是应该更快吗?
解答
1. 返回空列表的原因
原代码中的window_sum是动态滚动更新的:每次循环都会将其减去窗口左端的旧元素,加上窗口右端的新元素,得到当前滑动窗口的实时和。
但列表推导式里的window_sum自始至终都是初始值sum(aby[:scan_window_size]),没有任何更新。推导式里计算的window_sum - aby[i] + aby[scan_window_size+i],是用初始窗口和做的单次计算,完全不等于原代码中滚动更新后的实时窗口和。
原代码中满足条件的是滚动更新后的窗口和,而推导式里的数值不符合> adj_qth_amp的判断条件,因此返回空列表。另外,原代码向列表添加的是索引i,但推导式添加的是计算出的数值,这也是逻辑错误,但并非返回空列表的直接原因。
2. 运行时间翻倍的原因
- 原代码每个循环只计算一次窗口和的更新操作,之后直接用这个更新后的值做判断,计算量是单次的。
- 列表推导式中,每个循环要重复计算两次完全相同的表达式:一次在
if判断里做条件校验,一次在列表元素生成时取值。相当于每个循环执行了两次减法和加法操作,计算量直接翻倍,因此耗时也翻倍。
关于“列表推导式更快”的误区:列表推导式确实比手动循环调用append高效,但前提是逻辑等价且计算量相当。你这里的推导式不仅逻辑错误,还存在重复计算,自然比原代码慢。
内容的提问来源于stack exchange,提问作者bentrification
相关产品推荐
相关产品推荐

