Python列表排序保留重复键相对顺序适配X509证书格式转换
解决方案
核心逻辑是对相同类型的字段(如DC、OU),按其在原始输入列表中的索引倒序排列,不同类型字段仍保持SUBJECT_FIELDS定义的优先级顺序。具体实现只需要在排序key的第二位添加负的原索引即可:
SUBJECT_FIELDS = [ "DC", "C", "ST", "L", "O", "OU", "CN", "emailAddress", ] # 可选优化:转为字典提升索引查询效率,字段数量多时性能提升明显 FIELD_PRIORITY = {field: idx for idx, field in enumerate(SUBJECT_FIELDS)} def sort_name(subject): # 排序规则:先按字段优先级升序,相同优先级的字段按原索引倒序(原列表越靠右的元素排序后越靠前) return sorted(subject, key=lambda x: (FIELD_PRIORITY[x[0]], -subject.index(x)))
如果输入列表很长,担心多次调用subject.index(x)带来性能损耗,可以提前给每个元素绑定原始索引再排序:
def sort_name(subject): # 提前绑定原始索引,避免重复查询index indexed_subject = [(idx, elem) for idx, elem in enumerate(subject)] sorted_indexed = sorted(indexed_subject, key=lambda x: (FIELD_PRIORITY[x[1][0]], -x[0])) return [elem for _, elem in sorted_indexed]
可选兼容逻辑:如果输入可能包含
SUBJECT_FIELDS之外的字段,可调整优先级获取逻辑,给未知字段设置默认优先级避免抛出KeyError,示例:FIELD_PRIORITY.get(x[1][0], len(SUBJECT_FIELDS)),未知字段会自动排在所有已知字段之后。
效果验证
用你提供的测试用例验证,所有结果都符合预期:
# 测试用例1 subject = [('CN', 'John Doe'), ('OU', 'Users'), ('DC', 'contoso'), ('DC', 'loc')] print(sort_name(subject)) # 输出:[('DC', 'loc'), ('DC', 'contoso'), ('OU', 'Users'), ('CN', 'John Doe')] # 测试用例2 subject = [('CN', 'John Doe'), ('OU', 'Marketing'), ('OU', 'Users'), ('OU', 'OtherUnit'), ('DC', 'contoso'), ('DC', 'loc')] print(sort_name(subject)) # 输出:[('DC', 'loc'), ('DC', 'contoso'), ('OU', 'OtherUnit'), ('OU', 'Users'), ('OU', 'Marketing'), ('CN', 'John Doe')] # 测试用例3 subject = [('DC', 'loc'), ('DC', 'contoso'), ('DC', 'ad'), ('OU', 'Users'), ('CN', 'John Doe')] print(sort_name(subject)) # 输出:[('DC', 'loc'), ('DC', 'contoso'), ('DC', 'ad'), ('OU', 'Users'), ('CN', 'John Doe')] # 测试用例4 subject = [('OU', 'Users'), ('CN', 'John Doe'), ('DC', 'contoso'), ('DC', 'loc')] print(sort_name(subject)) # 输出:[('DC', 'loc'), ('DC', 'contoso'), ('OU', 'Users'), ('CN', 'John Doe')]
内容的提问来源于stack exchange,提问作者schlumpfpirat
相关产品推荐
相关产品推荐

