优化字典列表值迭代统计:计算历史频次覆盖当前元素的方案
问题需求
现有一个以升序日期字符串为键、整数列表为值的字典,需完成以下计算:
- 对每个键值对,遍历两组参数:过去记录次数P(取值7、8、9),出现次数阈值M(取值2、3)
- 统计过去P次记录中出现次数≥M的数字,与当前键对应列表数字的交集数量
- 示例:键
L19981120对应的列表[2,3,5]中,有2个数字在过去9次记录中出现了至少3次
当前实现存在代码冗余、仅输出部分迭代结果的问题,需要更优的正确实现方式。
现有实现代码
data = { "L19980909": [11,12,25], "L19981013": [19,28,31], "L19981016": [4,9,31], "L19981020": [8,11,17], "L19981023": [5,22,25], "L19981027": [5,20,27], "L19981030": [12,19,26], "L19981105": [31,32,38], "L19981109": [2,22,24], "L19981110": [2,16,19], "L19981113": [9,15,17], "L19981119": [2,10,11], "L19981120": [2,3,5], "L19981126": [4,6,14], "L19981127": [5,9,18], "L19981201": [1,6,7]} value_list = list(data.values()) for idx, (k, v) in enumerate(data.items()): ever_more_than_times = [] for how_many_past in [7,8,9]: if idx >= how_many_past: past_appeared = sum(value_list[idx-how_many_past:idx],[]) for more_than_times in [2,3]: if how_many_past > more_than_times: for ox in list(range(1,40)): if past_appeared.count(ox) >= more_than_times: ever_more_than_times.append(ox) ever_more_than_times = list(set(ever_more_than_times)) hit = len(set(ever_more_than_times) & set(v)) if hit != 0: print (k,'$',v,'$',how_many_past,'$',more_than_times,'$',hit)
现有输出
L19981105 $ [31, 32, 38] $ 9 $ 3 $ 1 L19981110 $ [2, 16, 19] $ 9 $ 3 $ 1 L19981119 $ [2, 10, 11] $ 9 $ 3 $ 1 L19981120 $ [2, 3, 5] $ 9 $ 3 $ 2 L19981127 $ [5, 9, 18] $ 9 $ 3 $ 1
优化后的实现代码
from collections import defaultdict data = { "L19980909": [11,12,25], "L19981013": [19,28,31], "L19981016": [4,9,31], "L19981020": [8,11,17], "L19981023": [5,22,25], "L19981027": [5,20,27], "L19981030": [12,19,26], "L19981105": [31,32,38], "L19981109": [2,22,24], "L19981110": [2,16,19], "L19981113": [9,15,17], "L19981119": [2,10,11], "L19981120": [2,3,5], "L19981126": [4,6,14], "L19981127": [5,9,18], "L19981201": [1,6,7] } # 提取按日期升序排列的记录列表(Python3.7+字典保留插入顺序) record_list = list(data.items()) for idx, (current_key, current_nums) in enumerate(record_list): current_num_set = set(current_nums) # 遍历所有P和M的参数组合 for P in [7, 8, 9]: if idx < P: continue # 历史记录不足P条,跳过 # 收集过去P次记录的所有数字 past_nums = [] for _, nums in record_list[idx-P:idx]: past_nums.extend(nums) # 统计数字出现次数 count_dict = defaultdict(int) for num in past_nums: count_dict[num] += 1 # 遍历M阈值 for M in [2, 3]: # 筛选出符合次数要求的数字集合 qualified_nums = {num for num, cnt in count_dict.items() if cnt >= M} # 计算交集数量 hit_count = len(current_num_set & qualified_nums) # 输出结果,可根据需求修改输出格式或过滤条件 print(f"{current_key} $ {current_nums} $ {P} $ {M} $ {hit_count}")
优化点说明
- 修复输出不完整问题:原代码仅保留最后一组P、M参数的结果,优化后遍历所有P和M的组合,输出每个键值对对应所有参数的计算结果
- 提升性能:
- 用
defaultdict统计数字出现次数,替代原代码中反复调用list.count()的低效操作(原代码每次count都会遍历整个列表,时间复杂度O(n),优化后仅遍历一次) - 提前将当前列表转为集合,减少交集计算的时间开销
- 用
- 简化逻辑:减少嵌套层级,变量命名更直观,代码结构清晰易读
- 兼容性:依赖Python3.7+的字典插入顺序特性,符合原数据升序日期的要求
内容的提问来源于stack exchange,提问作者Mark K
相关产品推荐
相关产品推荐

