嵌套字典按x0排序触发KeyError及text字段同步排序问题
问题分析
你遇到的KeyError: 'x0'是因为你直接对nested.values()排序,而nested.values()返回的是外层字典对应的内层字典(比如{1: {'x0': ...}, 2: {'x0': ...}}),你试图直接取这个内层字典的'x0'键,当然找不到——x0是内层字典里每个子字典的键,不是内层字典本身的键。
另外你提到之前的方案只排了x0、text没同步,那是因为排序逻辑没把整个子字典作为排序单元,只单独处理了x0值,导致关联的text字段没跟着移动。
解决方案
根据你的需求(把内层条目按x0从小到大排序,同时保留text和x0的关联,甚至重新编号内层键),这里有两种常用实现:
方案1:保留原内层键,按x0排序条目
如果想保留原来的内层键(比如排序后内层键还是1、2,但对应的值按x0排序),可以对内层字典的键值对进行排序,再重新组合成字典:
from decimal import Decimal # 假设你的nested字典已定义 sorted_nested = {} for outer_key, inner_dict in nested.items(): # 对内层字典的键值对按子字典的x0值排序 sorted_items = sorted(inner_dict.items(), key=lambda item: item[1]['x0']) # Python3.7+字典默认保留插入顺序,直接转成字典即可 sorted_nested[outer_key] = dict(sorted_items)
比如你给出的示例:
原内层字典{1: {'text': 'My email is', 'x0': Decimal('223.560')}, 2: {'text': 'example@domain.com', 'x0': Decimal('21.600')}}
排序后会变成{2: {'text': 'example@domain.com', 'x0': Decimal('21.600')}, 1: {'text': 'My email is', 'x0': Decimal('223.560')}}
方案2:重新编号内层键,按x0排序后从1开始
如果希望排序后内层键从1开始递增(和你给出的示例结果完全一致),可以先提取内层的子字典列表按x0排序,再重新生成带有序键的内层字典:
from decimal import Decimal sorted_nested = {} for outer_key, inner_dict in nested.items(): # 提取内层的子字典,按x0值排序 sorted_sub_dicts = sorted(inner_dict.values(), key=lambda d: d['x0']) # 重新生成内层字典,键从1开始计数 sorted_inner = {i + 1: sub_dict for i, sub_dict in enumerate(sorted_sub_dicts)} sorted_nested[outer_key] = sorted_inner
这个方案处理你的示例后,会得到你想要的结果:{2: {1: {'text': 'example@domain.com', 'x0': Decimal('21.600')}, 2: {'text': 'My email is', 'x0': Decimal('223.560')}}}
验证说明
两种方案都能保证text和x0字段同步排序,不会出现字段分离的问题。如果你的Python版本低于3.7,想要严格保证字典有序,可以用collections.OrderedDict替代普通字典,比如把dict(sorted_items)换成OrderedDict(sorted_items)。
内容的提问来源于stack exchange,提问作者oliverbj

