如何使用natsort实现字典列表先按前缀升序再按版本号排序?
按前缀升序+版本号自然排序的实现
原始数据
my_list = [ {'id': 'Bear@1.0.1'}, {'id': 'Bear@5.5.1'}, {'id': 'Bear@10.0.9'}, {'id': 'Bear@5.1'}, {'id': 'Air@7.6'}, {'id': 'Air@8.7'}, {'id': 'Air@10.0.0'}, {'id': 'Air@1.0'} ]
需求
先按id字段中@符号前的内容(如Air、Bear)升序排序,再按@后的版本号做符合版本逻辑的自然排序(例如1.0 < 7.6 < 10.0.0,5.1 < 5.5.1)。
问题分析
当前使用代码:
natsort.natsorted(my_list, key=itemgetter('id'), reverse=True)
得到的结果中Bear类条目排在Air类之前,原因是reverse=True会对整个id字符串的自然排序结果做反转,而Bear@...的字符串整体字典序大于Air@...,反转后就会排在前面,不符合前缀升序的要求。
解决方案
核心思路是将排序拆分为两个独立维度:先按前缀升序排列,再对每个前缀下的版本号做自然排序。通过自定义排序key实现这一逻辑:
代码实现
from operator import itemgetter from natsort import natsorted, natsort_keygen # 生成版本号自然排序的key函数 version_key = natsort_keygen() # 自定义排序key:(前缀, 版本号自然排序key) sorted_list = natsorted( my_list, key=lambda x: (x['id'].split('@')[0], version_key(x['id'].split('@')[1])) )
排序结果
执行后得到的正确排序结果:
[ {'id': 'Air@1.0'}, {'id': 'Air@7.6'}, {'id': 'Air@8.7'}, {'id': 'Air@10.0.0'}, {'id': 'Bear@1.0.1'}, {'id': 'Bear@5.1'}, {'id': 'Bear@5.5.1'}, {'id': 'Bear@10.0.9'} ]
逻辑说明
- 前缀排序:通过
x['id'].split('@')[0]提取@前的前缀,利用Python默认的字符串升序排序,让字典序更小的Air排在Bear之前。 - 版本号排序:借助
natsort_keygen()生成的key函数,对@后的版本号做自然排序,保证版本号的比较符合实际的版本逻辑(而非单纯的字符串字典序)。
内容的提问来源于stack exchange,提问作者A Diehl
相关产品推荐
相关产品推荐

