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

Python嵌套对象扁平化/聚合的高效算法优化咨询

优化嵌套对象聚合的速度问题

你的思路方向是对的,但现有实现确实有可以提速的空间——主要是减少重复计算和避免冗余操作。咱们一步步来拆解优化点:

核心问题分析

你的代码里有两个明显的性能损耗点:

  • 每次循环都重复计算len(donation["organization"]["states"])和len(organization["states"]),对于大量数据来说,这是不必要的重复运算
  • 处理机构预算时,每个州的name被重复赋值多次(比如Org1的MA州会被赋值两次),虽然不影响结果,但属于冗余操作

优化方案一:预计算重复值,合并逻辑

先预处理机构的预算分配(因为organizations是去重后的列表,只需要处理一次),同时预计算每个机构的州数量,避免重复计算。然后处理捐赠数据时也复用这个预计算的值:

from collections import defaultdict

def get_stats():
    return {"total_donations": 0.0, "total_budget": 0.0, "name": ""}

results = defaultdict(get_stats)

# 第一步:预处理机构预算,同时记录机构的州数量和州信息
org_state_info = {}
for org in organizations:
    state_count = len(org["states"])
    budget_per_state = org["total_budget"] / state_count
    org_state_info[org["name"]] = {
        "state_count": state_count,
        "states": org["states"]
    }
    # 分配预算到各州
    for state in org["states"]:
        code = state["code"]
        results[code]["total_budget"] += budget_per_state
        # 只赋值一次name,避免重复操作
        if not results[code]["name"]:
            results[code]["name"] = state["name"]

# 第二步:处理捐赠数据,复用预计算的州数量
for donation in donations:
    org_name = donation["organization"]["name"]
    state_count = org_state_info[org_name]["state_count"]
    donation_per_state = donation["amount"] / state_count
    # 分配捐赠到各州
    for state in org_state_info[org_name]["states"]:
        results[state["code"]]["total_donations"] += donation_per_state

这个版本的优势:

  • 每个机构的州数量只计算一次,不再每次循环都调用len()
  • 州的name只赋值一次,减少冗余的字符串赋值操作
  • 通过org_state_info缓存机构的州信息,避免重复从donation对象里嵌套取值(嵌套字典访问比直接访问缓存的dict稍慢)

优化方案二:用普通字典代替defaultdict(可选)

如果数据量极大,普通字典的访问速度会略快于defaultdict,可以手动初始化州的统计信息:

results = {}

# 处理机构预算时初始化州信息
for org in organizations:
    state_count = len(org["states"])
    budget_per_state = org["total_budget"] / state_count
    for state in org["states"]:
        code = state["code"]
        if code not in results:
            results[code] = {
                "name": state["name"],
                "total_donations": 0.0,
                "total_budget": 0.0
            }
        results[code]["total_budget"] += budget_per_state

# 处理捐赠
for donation in donations:
    org = donation["organization"]
    state_count = len(org["states"])
    donation_per_state = donation["amount"] / state_count
    for state in org["states"]:
        results[state["code"]]["total_donations"] += donation_per_state

这种方式避免了defaultdict的函数调用开销,在数据量很大时能看到明显提速。

关于map/reduce的疑问

Python中的map()和functools.reduce()在这种场景下并不会比优化后的循环更快——因为循环本身已经是Python中比较高效的迭代方式,而map/reduce会引入额外的函数调用开销。除非你用numpy或pandas这类向量化运算的库,否则纯Python里优化循环内的操作比切换到map/reduce更有效。

如果你的数据集非常大(百万级以上),可以考虑用pandas来处理,它的向量化运算会比纯Python循环快得多。比如:

import pandas as pd

# 把捐赠数据扁平化
donation_df = pd.json_normalize(donations, record_path=["organization", "states"], 
                                meta=["amount", ["organization", "name"], ["organization", "total_budget"]])
# 计算每个捐赠对应的州分配金额
donation_df["donation_per_state"] = donation_df["amount"] / donation_df.groupby(["organization.name"])["code"].transform("count")
# 计算机构预算的州分配额
donation_df["budget_per_state"] = donation_df["organization.total_budget"] / donation_df.groupby(["organization.name"])["code"].transform("count")

# 按州聚合
result_df = donation_df.groupby(["code", "name"]).agg(
    total_donations=("donation_per_state", "sum"),
    total_budget=("budget_per_state", "sum")
).reset_index()

# 转换成目标格式
results = result_df.set_index("code").to_dict("index")

这个方案在大数据量下的性能会远超纯Python循环,但学习成本稍高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 13:02:42