如何更优雅地转换字典的嵌套数据结构?
如何更优雅地转换字典的嵌套数据结构?
嘿,你的需求我完全懂——要把三层嵌套字典的层级顺序从subject -> period -> zodiak调换为zodiak -> period -> subject,你的代码逻辑是对的,能正常工作,但确实有更简洁优雅的写法,我给你分享几个实用的思路:
方法一:用collections.defaultdict简化初始化
原代码里反复判断键是否存在的部分有点繁琐,Python的defaultdict可以帮我们自动生成嵌套的空字典,省去这些重复判断:
from collections import defaultdict def transform_data(self, data): """ before: data[subject][period][zodiak] = content after : data[zodiak][period][subject] = content """ # 定义嵌套的defaultdict:zodiak对应一个defaultdict,里面的period对应普通dict result = defaultdict(lambda: defaultdict(dict)) for subject, subject_data in data.items(): for period, period_data in subject_data.items(): for zodiak, content in period_data.items(): # 直接赋值即可,不存在的键会自动创建对应的空字典 result[zodiak][period][subject] = content # (可选)如果需要把defaultdict转为普通字典(比如要JSON序列化),可以用下面的转换函数 def _defaultdict_to_dict(d): if isinstance(d, defaultdict): return {k: _defaultdict_to_dict(v) for k, v in d.items()} return d return _defaultdict_to_dict(result)
这样代码一下子清爽了很多,而且逻辑和你的原代码完全一致,只是把重复的键存在性判断交给了defaultdict处理。
方法二:用嵌套字典推导式(适合数据结构规整的场景)
如果你的数据是完全规整的——每个subject下的所有period都包含相同的zodiak,每个period都存在于所有subject中,那可以用嵌套的字典推导式来实现转换:
def transform_data(self, data): """ before: data[subject][period][zodiak] = content after : data[zodiak][period][subject] = content """ # 先提取所有唯一的zodiak和period all_zodiaks = {z for sd in data.values() for pd in sd.values() for z in pd.keys()} all_periods = {p for sd in data.values() for p in sd.keys()} return { zodiak: { period: { subject: data[subject][period][zodiak] for subject in data } for period in all_periods } for zodiak in all_zodiaks }
不过这个写法的缺点是如果数据有缺失(比如某个subject的period里没有某个zodiak),会抛出KeyError,所以只适合数据结构完全一致的场景,可读性也不如defaultdict的版本。
最后想说的
其实你的原代码逻辑非常清晰,完全是正确的实现方式,上面的优化只是利用Python的工具类或者语法糖来减少重复代码,核心逻辑还是和你原来的思路一样哒~
备注:内容来源于stack exchange,提问作者Harm
相关产品推荐
相关产品推荐

