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

如何高效合并含相同month时间戳的多字典列表?

问题

我有一个包含100余个字典的列表,每个字典包含month(datetime类型)及各类状态统计值,示例数据如下:

[
    {'month': datetime.datetime(2022, 4, 1, 0, 0, tzinfo=zoneinfo.ZoneInfo(key='UTC')), 'total': 1, 'Win': 0, 'Loss': 1, 'Open': 0, 'Dormant': 0, 'Pending': 0, 'Cancelled': 0},
    {'month': datetime.datetime(2022, 5, 1, 0, 0, tzinfo=zoneinfo.ZoneInfo(key='UTC')), 'total': 1, 'Win': 0, 'Loss': 0, 'Open': 1, 'Dormant': 0, 'Pending': 0, 'Cancelled': 0},
    {'month': datetime.datetime(2022, 5, 1, 0, 0, tzinfo=zoneinfo.ZoneInfo(key='UTC')), 'total': 1, 'Win': 0, 'Loss': 1, 'Open': 0, 'Dormant': 0, 'Pending': 0, 'Cancelled': 0},
    {'month': datetime.datetime(2022, 5, 1, 0, 0, tzinfo=zoneinfo.ZoneInfo(key='UTC')), 'total': 1, 'Win': 0, 'Loss': 1, 'Open': 0, 'Dormant': 0, 'Pending': 0, 'Cancelled': 0},
    {'month': datetime.datetime(2022, 5, 1, 0, 0, tzinfo=zoneinfo.ZoneInfo(key='UTC')), 'total': 1, 'Win': 0, 'Loss': 0, 'Open': 1, 'Dormant': 0, 'Pending': 0, 'Cancelled': 0},
    {'month': datetime.datetime(2022, 6, 1, 0, 0, tzinfo=zoneinfo.ZoneInfo(key='UTC')), 'total': 1, 'Win': 0, 'Loss': 0, 'Open': 1, 'Dormant': 0, 'Pending': 0, 'Cancelled': 0},
    {'month': datetime.datetime(2022, 7, 1, 0, 0, tzinfo=zoneinfo.ZoneInfo(key='UTC')), 'total': 1, 'Win': 0, 'Loss': 0, 'Open': 1, 'Dormant': 0, 'Pending': 0, 'Cancelled': 0}
]

需求:将所有字典按相同month时间戳合并,每个时间戳仅保留一个字典,对应统计值求和,预期输出如下:

[
    {'month': datetime.datetime(2022, 4, 1, 0, 0, tzinfo=zoneinfo.ZoneInfo(key='UTC')), 'total': 1, 'Win': 0, 'Loss': 1, 'Open': 0, 'Dormant': 0, 'Pending': 0, 'Cancelled': 0},
    {'month': datetime.datetime(2022, 5, 1, 0, 0, tzinfo=zoneinfo.ZoneInfo(key='UTC')), 'total': 4, 'Win': 0, 'Loss': 2, 'Open': 2, 'Dormant': 0, 'Pending': 0, 'Cancelled': 0},
    {'month': datetime.datetime(2022, 6, 1, 0, 0, tzinfo=zoneinfo.ZoneInfo(key='UTC')), 'total': 1, 'Win': 0, 'Loss': 0, 'Open': 1, 'Dormant': 0, 'Pending': 0, 'Cancelled': 0},
    {'month': datetime.datetime(2022, 7, 1, 0, 0, tzinfo=zoneinfo.ZoneInfo(key='UTC')), 'total': 1, 'Win': 0, 'Loss': 0, 'Open': 1, 'Dormant': 0, 'Pending': 0, 'Cancelled': 0}
]

我之前尝试循环比对前一个对象的方法,耗时过长,请问最高效的实现方式是什么?

高效实现方案

方法1:原生Python字典分组(O(n)时间复杂度,最优解)

利用字典键查找O(1)的特性,以month为键分组,仅遍历一次列表即可完成统计,是当前数据量下的最快方案:

import datetime
import zoneinfo

def merge_monthly_data(data):
    grouped = {}
    for item in data:
        month_key = item['month']
        if month_key in grouped:
            # 累加所有统计字段
            for key in ['total', 'Win', 'Loss', 'Open', 'Dormant', 'Pending', 'Cancelled']:
                grouped[month_key][key] += item[key]
        else:
            # 首次出现该月份,复制条目到分组字典
            grouped[month_key] = item.copy()
    # 转换为列表,如需按时间排序可追加sorted逻辑
    return list(grouped.values())

# 测试示例数据
sample_data = [
    {'month': datetime.datetime(2022, 4, 1, 0, 0, tzinfo=zoneinfo.ZoneInfo(key='UTC')), 'total': 1, 'Win': 0, 'Loss': 1, 'Open': 0, 'Dormant': 0, 'Pending': 0, 'Cancelled': 0},
    {'month': datetime.datetime(2022, 5, 1, 0, 0, tzinfo=zoneinfo.ZoneInfo(key='UTC')), 'total': 1, 'Win': 0, 'Loss': 0, 'Open': 1, 'Dormant': 0, 'Pending': 0, 'Cancelled': 0},
    {'month': datetime.datetime(2022, 5, 1, 0, 0, tzinfo=zoneinfo.ZoneInfo(key='UTC')), 'total': 1, 'Win': 0, 'Loss': 1, 'Open': 0, 'Dormant': 0, 'Pending': 0, 'Cancelled': 0},
    {'month': datetime.datetime(2022, 5, 1, 0, 0, tzinfo=zoneinfo.ZoneInfo(key='UTC')), 'total': 1, 'Win': 0, 'Loss': 1, 'Open': 0, 'Dormant': 0, 'Pending': 0, 'Cancelled': 0},
    {'month': datetime.datetime(2022, 5, 1, 0, 0, tzinfo=zoneinfo.ZoneInfo(key='UTC')), 'total': 1, 'Win': 0, 'Loss': 0, 'Open': 1, 'Dormant': 0, 'Pending': 0, 'Cancelled': 0},
    {'month': datetime.datetime(2022, 6, 1, 0, 0, tzinfo=zoneinfo.ZoneInfo(key='UTC')), 'total': 1, 'Win': 0, 'Loss': 0, 'Open': 1, 'Dormant': 0, 'Pending': 0, 'Cancelled': 0},
    {'month': datetime.datetime(2022, 7, 1, 0, 0, tzinfo=zoneinfo.ZoneInfo(key='UTC')), 'total': 1, 'Win': 0, 'Loss': 0, 'Open': 1, 'Dormant': 0, 'Pending': 0, 'Cancelled': 0}
]

result = merge_monthly_data(sample_data)
for item in result:
    print(item)

说明:datetime对象是可哈希类型,可直接作为字典键。该方法时间复杂度为O(n),远优于循环比对的O(n²)方案。如需结果按时间排序,可将返回语句改为:

return sorted(grouped.values(), key=lambda x: x['month'])

方法2:使用Pandas(适合复杂统计场景)

如果后续需要更多数据处理操作,Pandas的分组聚合功能代码更简洁,性能对于100+数据量完全够用:

import pandas as pd
import datetime
import zoneinfo

sample_data = [
    # 同上示例数据
]

# 转换为DataFrame
df = pd.DataFrame(sample_data)
# 按month分组并求和统计字段
merged_df = df.groupby('month').sum().reset_index()
# 转换回字典列表
result = merged_df.to_dict('records')

print(result)

说明:Pandas内部优化了分组逻辑,无需手动遍历累加,适合需要后续数据分析的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 01:15:39