如何对键名相似的字典值进行求和?求更优实现方案
字典对应字段求和的更优实现
问题背景
给定如下字典数据:
d={} d['rb2401_long'] = {'Position': 20, 'LongFrozen': 1, 'ShortFrozen': 5} d['yd_rb2401_long'] = {'Position': 10, 'LongFrozen': 2, 'ShortFrozen': 3} d['rb2401_short'] = {'Position': 30, 'LongFrozen': 10, 'ShortFrozen': 6} d['yd_rb2401_short'] = {'Position': 15, 'LongFrozen': 8, 'ShortFrozen': 2} d['sc2311_long'] = {'Position': 200, 'LongFrozen': 0, 'ShortFrozen': 50} d['yd_sc2311_long'] = {'Position': 100, 'LongFrozen': 20, 'ShortFrozen': 30} d['sc2311_short'] = {'Position': 300, 'LongFrozen': 100, 'ShortFrozen': 60} d['yd_sc2311_short'] = {'Position': 150, 'LongFrozen': 80, 'ShortFrozen': 20}
需要将形如rb2401_long和yd_rb2401_long的子字典对应字段求和,生成rb2401_long_result这样的结果,例如:
d['rb2401_long_result']={'Position': 30, 'LongFrozen': 3, 'ShortFrozen': 8}
当前的实现代码如下:
r={} for key,values in d.items(): rk=key.split('yd_')[-1] if rk in r: r[rk]['Position']+=values['Position'] r[rk]['LongFrozen']+=values['LongFrozen'] r[rk]['ShortFrozen']+=values['ShortFrozen'] else: r[rk]=values
更优实现方式
1. 灵活处理任意字段(推荐)
原实现硬编码了字段名,后续字段变动时需要修改代码。下面的方式用collections.defaultdict自动遍历所有字段,扩展性更强,同时避免修改原字典的引用:
from collections import defaultdict def merge_position_dicts(src_dict): merged = defaultdict(lambda: defaultdict(int)) # 遍历原字典的所有键值对 for key, sub_dict in src_dict.items(): # 获取基准键(去掉yd_前缀) base_key = key.split('yd_')[-1] # 累加每个字段的值 for field, value in sub_dict.items(): merged[base_key][field] += value # 转换为普通字典并添加_result后缀 return {f"{k}_result": dict(v) for k, v in merged.items()} # 调用并将结果更新到原字典 result = merge_position_dicts(d) d.update(result)
2. 固定字段下的简洁写法
如果确定字段只会是Position、LongFrozen、ShortFrozen,可以用分组求和的方式:
from itertools import groupby # 按基准键排序后分组 sorted_items = sorted(d.items(), key=lambda x: x[0].split('yd_')[-1]) groups = groupby(sorted_items, key=lambda x: x[0].split('yd_')[-1]) result = {} for base_key, items in groups: item_list = list(items) result[f"{base_key}_result"] = { 'Position': sum(i[1]['Position'] for i in item_list), 'LongFrozen': sum(i[1]['LongFrozen'] for i in item_list), 'ShortFrozen': sum(i[1]['ShortFrozen'] for i in item_list) } d.update(result)
3. 直接指定目标键的精准实现
如果只需要处理已知的几个目标键,这种方式更高效:
target_keys = ['rb2401_long', 'rb2401_short', 'sc2311_long', 'sc2311_short'] for key in target_keys: # 取出原字典中的两个子字典,不存在则用空字典兜底 dict1 = d.get(key, {}) dict2 = d.get(f"yd_{key}", {}) # 对应字段求和 d[f"{key}_result"] = { k: dict1.get(k, 0) + dict2.get(k, 0) for k in ['Position', 'LongFrozen', 'ShortFrozen'] }
原实现的问题点
- 引用修改风险:
r[rk]=values直接将原字典的子字典引用赋值给r,后续修改r中的字段会同时修改原字典d的内容,可能引发意外问题。 - 扩展性差:硬编码字段名,新增或修改字段时需要同步修改代码。
内容的提问来源于stack exchange,提问作者July
相关产品推荐
相关产品推荐

