IronPython 2.7.4中可否合并多组同筛选逻辑的列表推导式?
实现优化方案
原实现的问题
原代码存在两处可优化的问题:
- 第一行列表推导式直接覆盖原始
enids变量,后续两个推导式枚举的是筛选后缩短的enids序列,而非原始序列的索引,最终匹配到的s、t值会出现位置错位,不符合"保留原enids位置对应s、t值"的需求 - 三次独立遍历enids执行完全相同的
enid in nids判断,没有复用筛选逻辑,产生不必要的重复时间开销
适配IronPython 2.7.4的优化实现
首先对nids做预处理,转为集合类型,将成员判断的时间复杂度从列表的O(n)线性查找降低到集合的O(1)常量级查找;之后单次遍历所有同位置的序列元素,一次完成筛选和值收集,无需重复循环。
写法1:显式循环收集(性能最优,完全兼容IronPython 2.7特性)
# 预处理:将nids转为集合,降低成员判断开销 nid_set = set(nids) # 初始化三个空列表存放筛选结果 filtered_enids = [] filtered_s = [] filtered_t = [] # 单次遍历三个序列的同位置元素,匹配筛选条件 for enid, s_val, t_val in zip(enids, s, t): if enid in nid_set: filtered_enids.append(enid) filtered_s.append(s_val) filtered_t.append(t_val)
以给出的测试数据为例,执行后最终结果为:
filtered_enids: [1,2,2,3,4,5,5,6]filtered_s: [44,33,68,43,43,53,55,69]filtered_t: [50,40,30,10,60,50,80,90]
写法2:推导式+元组解包(代码更简洁)
偏好紧凑推导式写法的话,可以通过打包元组后解包实现,同样仅遍历一次数据:
nid_set = set(nids) filtered_enids, filtered_s, filtered_t = [list(x) for x in zip(*[ (enid, s_val, t_val) for enid, s_val, t_val in zip(enids, s, t) if enid in nid_set ])]
优化收益
- 时间开销降低:将三次独立遍历合并为一次,配合集合的O(1)常量级成员判断,整体运行效率可提升数倍
- 逻辑一致性:所有筛选规则仅维护一处,避免多段重复代码的逻辑不一致问题
- 无变量覆盖风险:全程保留原始输入序列,不会因为重写变量引发索引错位的隐蔽bug
内容的提问来源于stack exchange,提问作者Gokulnath Thangavel
相关产品推荐
相关产品推荐

