You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于键名对元组列表求平均值:能否简化代码或单行实现?

简化元组列表按日期分组求平均值的Python代码

当然可以简化!甚至能写出单行的实现方式,下面给你几种不同的思路,从精简代码到单行写法逐步优化:

方法一:用collections.defaultdict替代setdefault,精简循环

原来的setdefault每次都要判断键是否存在,换成defaultdict(list)可以直接给键对应的列表追加值,再配合字典推导式替换第二次循环,代码清爽很多:

from collections import defaultdict

modifiedL = [('10-1984', 2.8), ('10-1984', 2.8), ('10-1984', 2.85), ('10-1984', 2.82), ('10-1984', 2.78), ('10-1984', 2.75), ('09-1984', 2.82), ('09-1984', 2.9), ('09-1984', 2.9), ('09-1984', 2.94), ('09-1984', 2.99), ('09-1984', 3.02), ('09-1984', 3.05), ('09-1984', 3.04), ('09-1984', 3.11), ('09-1984', 3.22), ('09-1984', 3.13), ('09-1984', 3.09), ('09-1984', 2.94), ('09-1984', 3.02), ('09-1984', 2.97), ('09-1984', 2.98)]

avg = defaultdict(list)
for date, value in modifiedL:
    avg[date].append(value)
# 用字典推导式直接计算平均值
avg = {date: sum(values)/len(values) for date, values in avg.items()}

这个写法保持了原逻辑的直观性,同时减少了冗余代码。

方法二:用itertools.groupby实现分组计算

itertools.groupby是Python标准库中专门用于分组的工具,不过要注意必须先对列表按日期排序——因为groupby只会把连续的相同键归为一组,不排序的话会漏分组:

from itertools import groupby

modifiedL = [('10-1984', 2.8), ('10-1984', 2.8), ('10-1984', 2.85), ('10-1984', 2.82), ('10-1984', 2.78), ('10-1984', 2.75), ('09-1984', 2.82), ('09-1984', 2.9), ('09-1984', 2.9), ('09-1984', 2.94), ('09-1984', 2.99), ('09-1984', 3.02), ('09-1984', 3.05), ('09-1984', 3.04), ('09-1984', 3.11), ('09-1984', 3.22), ('09-1984', 3.13), ('09-1984', 3.09), ('09-1984', 2.94), ('09-1984', 3.02), ('09-1984', 2.97), ('09-1984', 2.98)]

# 先按日期排序
sorted_list = sorted(modifiedL, key=lambda x: x[0])
# 分组并计算平均值
avg = {}
for date, group in groupby(sorted_list, key=lambda x: x[0]):
    values = [val for _, val in group]
    avg[date] = sum(values)/len(values)

如果想更紧凑,可以用字典推导式(Python 3.8+支持海象运算符,避免重复遍历迭代器):

sorted_list = sorted(modifiedL, key=lambda x: x[0])
avg = {date: sum(val for _, val in group)/len(group) if (group := list(group)) else 0 for date, group in groupby(sorted_list, key=lambda x: x[0])}

方法三:真正的单行写法(可读性稍差,适合炫技)

如果一定要追求单行实现,可以把defaultdict和字典推导式结合起来,用匿名函数做中间处理:

from collections import defaultdict

modifiedL = [('10-1984', 2.8), ('10-1984', 2.8), ('10-1984', 2.85), ('10-1984', 2.82), ('10-1984', 2.78), ('10-1984', 2.75), ('09-1984', 2.82), ('09-1984', 2.9), ('09-1984', 2.9), ('09-1984', 2.94), ('09-1984', 2.99), ('09-1984', 3.02), ('09-1984', 3.05), ('09-1984', 3.04), ('09-1984', 3.11), ('09-1984', 3.22), ('09-1984', 3.13), ('09-1984', 3.09), ('09-1984', 2.94), ('09-1984', 3.02), ('09-1984', 2.97), ('09-1984', 2.98)]

avg = {k: sum(v)/len(v) for k, v in (lambda d: [(k, d[k]) for k in d])(defaultdict(list, {k: d[k].append(v) or d[k] for k, v in modifiedL}))}

不过这个写法可读性比较差,不推荐在生产代码中使用,更多是满足“单行”的需求。

方法四:用pandas一行搞定(适合数据处理场景)

如果你的项目已经在用pandas处理数据,那这个方法绝对是最简洁且可读性最高的:

import pandas as pd

modifiedL = [('10-1984', 2.8), ('10-1984', 2.8), ('10-1984', 2.85), ('10-1984', 2.82), ('10-1984', 2.78), ('10-1984', 2.75), ('09-1984', 2.82), ('09-1984', 2.9), ('09-1984', 2.9), ('09-1984', 2.94), ('09-1984', 2.99), ('09-1984', 3.02), ('09-1984', 3.05), ('09-1984', 3.04), ('09-1984', 3.11), ('09-1984', 3.22), ('09-1984', 3.13), ('09-1984', 3.09), ('09-1984', 2.94), ('09-1984', 3.02), ('09-1984', 2.97), ('09-1984', 2.98)]

avg = pd.DataFrame(modifiedL, columns=['date', 'value']).groupby('date')['value'].mean().to_dict()

pandas会帮你处理排序、分组、计算的所有细节,非常适合批量数据处理。

内容的提问来源于stack exchange,提问作者ehls39119

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:23:49