如何用更简洁的算法从列表筛选间隔大于指定值的元素
问题:实现间隔阈值过滤列表元素的简洁算法
给定列表
a = [44, 52, 59, 62, 174, 175, 178, 288, 292, 404, 408, 518, 521, 633, 637, 747, 751, 863, 867, 977, 980, 987]
需求说明
当指定间隔阈值为100时,最终过滤结果应为:
b = [62, 174, 288, 404, 518, 633, 747, 863, 977]
核心规则:
- 首先找到第一个满足下一个元素与当前元素差值大于阈值的元素,将其加入结果;
- 之后遍历列表,只要当前元素与结果中最后一个元素的差值大于阈值,就将当前元素加入结果。
现有实现代码
def pick(lst, gap): result = [] first_item_picked = False for idx, x in enumerate(lst): try: if not first_item_picked and idx < len(lst)-1 and lst[idx+1]-x > gap: first_item_picked = True result.append(x) elif x - lst[idx-1] > gap: result.append(x) except: print(idx,x) return result b = pick(a,100) print(b)
简洁实现方案
方案1:利用itertools.pairwise简化相邻元素对比(Python 3.10+)
通过pairwise直接获取相邻元素对,快速定位第一个符合条件的元素,再遍历后续元素筛选:
import itertools def pick(lst, gap): result = [] # 定位第一个需要保留的元素 for i, (curr, next_val) in enumerate(itertools.pairwise(lst)): if next_val - curr > gap: result.append(curr) last = curr # 遍历后续元素,筛选与上一个保留元素差值超阈值的项 for num in lst[i+1:]: if num - last > gap: result.append(num) last = num return result return result # 测试 a = [44, 52, 59, 62, 174, 175, 178, 288, 292, 404, 408, 518, 521, 633, 637, 747, 751, 863, 867, 977, 980, 987] print(pick(a, 100)) # 输出: [62, 174, 288, 404, 518, 633, 747, 863, 977]
方案2:纯遍历优化版(无依赖)
去掉冗余的try-except(边界可通过索引判断处理),逻辑更清晰:
def pick(lst, gap): result = [] n = len(lst) # 找第一个符合条件的元素 for i in range(n - 1): if lst[i+1] - lst[i] > gap: result.append(lst[i]) last = lst[i] # 处理后续元素 for num in lst[i+1:]: if num - last > gap: result.append(num) last = num return result return result # 无符合条件元素时返回空列表 # 测试 a = [44, 52, 59, 62, 174, 175, 178, 288, 292, 404, 408, 518, 521, 633, 637, 747, 751, 863, 867, 977, 980, 987] print(pick(a, 100))
方案3:生成器实现(代码更紧凑)
用生成器逐步产出结果,避免额外列表存储,适合处理大数据量:
def pick(lst, gap): it = iter(lst) try: prev = next(it) except StopIteration: return # 空列表直接返回 # 定位第一个保留元素 for curr in it: if curr - prev > gap: yield prev last = curr yield last break prev = curr # 筛选剩余元素 for curr in it: if curr - last > gap: yield curr last = curr # 测试 a = [44, 52, 59, 62, 174, 175, 178, 288, 292, 404, 408, 518, 521, 633, 637, 747, 751, 863, 867, 977, 980, 987] b = list(pick(a, 100)) print(b) # 输出: [62, 174, 288, 404, 518, 633, 747, 863, 977]
内容的提问来源于stack exchange,提问作者Niuya
相关产品推荐
相关产品推荐

