如何用Python标准库更优雅地实现周数据按月分组汇总?
嘿,我来帮你优化这段代码!你的原问题很典型——依赖输入列表按月份有序才能正确分组,一旦数据顺序打乱,结果就会出错,咱们用Python标准库就能写出更优雅、更健壮的实现,完全符合Pythonic风格~
问题分析
原代码的核心问题是必须依赖输入数据按月份连续排列,如果中间插入了其他月份的条目(比如把('2020/03/15', 56)放到2月的条目后面),就会错误地重复创建分组,导致汇总结果出错。接下来给你两种标准库的解决方案:
方案1:用collections.defaultdict(不依赖数据顺序)
这种方法最直观,不需要提前排序,直接遍历累加每个月份的值,时间复杂度是O(n),效率很高:
from collections import defaultdict sum_weekly = [('2020/01/05', 59), ('2020/01/19', 88), ('2020/01/26', 95), ('2020/02/02', 89), ('2020/02/09', 113), ('2020/02/16', 90), ('2020/02/23', 68), ('2020/03/01', 74), ('2020/03/08', 85), ('2020/04/19', 6), ('2020/04/26', 5), ('2020/05/03', 14), ('2020/05/10', 5), ('2020/05/17', 20), ('2020/05/24', 28),('2020/03/15', 56), ('2020/03/29', 5), ('2020/04/12', 2),] # 初始化一个默认值为0的字典,用来存每个月份的累加值 monthly_sum = defaultdict(int) for date_str, value in sum_weekly: # 提取日期中的月份部分 month = date_str.split('/')[1] monthly_sum[month] += value # 如果需要按月份顺序输出,用sorted排序;不需要的话直接转成list即可 out = sorted(monthly_sum.items(), key=lambda x: x[0]) print(out) # 输出:[('01', 242), ('02', 360), ('03', 220), ('04', 13), ('05', 67)]
优势:完全不依赖输入顺序,处理无序数据时更高效,逻辑清晰易懂。
方案2:用itertools.groupby(简洁的分组写法,需先排序)
如果你的数据可以接受先排序(或者本身就是有序的),groupby配合列表推导式的写法非常简洁,很有Python风格:
from itertools import groupby sum_weekly = [('2020/01/05', 59), ('2020/01/19', 88), ('2020/01/26', 95), ('2020/02/02', 89), ('2020/02/09', 113), ('2020/02/16', 90), ('2020/02/23', 68), ('2020/03/01', 74), ('2020/03/08', 85), ('2020/04/19', 6), ('2020/04/26', 5), ('2020/05/03', 14), ('2020/05/10', 5), ('2020/05/17', 20), ('2020/05/24', 28),('2020/03/15', 56), ('2020/03/29', 5), ('2020/04/12', 2),] # 先按月份对数据排序,因为groupby只能将连续的相同键分到一组 sorted_weekly = sorted(sum_weekly, key=lambda x: x[0].split('/')[1]) # 按月份分组,同时计算每组的总和 out = [ (month, sum(value for _, value in group)) for month, group in groupby(sorted_weekly, key=lambda x: x[0].split('/')[1]) ] print(out) # 输出同样是:[('01', 242), ('02', 360), ('03', 220), ('04', 13), ('05', 67)]
优势:代码简洁紧凑,用列表推导式完成分组+求和,符合Python的“简洁至上”原则。
两种方案对比
- 如果数据是无序的,优先选
defaultdict,效率更高(O(n) vs O(n log n)的排序开销); - 如果数据本身有序,或者你需要保持分组后的顺序和原有序列表一致,
groupby的写法更优雅。
内容的提问来源于stack exchange,提问作者rush dee
相关产品推荐
相关产品推荐

