Python如何对三元素zip列表排序:前两列降序第三列升序
多字段混合排序实现方案
问题原因
你之前的代码无法实现混合排序的核心原因是:sorted()函数的reverse=True参数会对key返回的所有排序字段统一应用降序规则,此时如果直接把名称字段加到sorter的返回元组里,名称也会按字典序降序排列,不符合第三列升序的要求。
Python原生元组排序遵循从左到右逐位比较、同位置值相等才比较下一位的规则,且默认是升序逻辑,我们可以利用这个特性给不同字段单独设置排序方向,不需要依赖全局reverse参数。
正确实现代码
names = ["name1", "McNamealot", "Namey Name Name", "Namey", "afirst"] scores = [1,3,42,42,5] world_rankings = [850,750,650,550,450] zipped = zip(world_rankings, scores, names) def sorter(item): # 前两个需要降序的数值字段返回相反数,第三个需要升序的字符串字段返回原值 return -item[0], -item[1], item[2] zipperoni = sorted(zipped, key=sorter)
逻辑说明
- 排序优先级完全匹配需求:元组返回值的顺序就是排序优先级顺序,先比对世界排名,再比对分数,最后比对名称。
- 降序实现逻辑:对于数值类型的排名、分数字段,返回字段值的相反数后,默认升序排序时,原值更大的条目对应的相反数更小,会自动排在前面,等价于单字段降序效果。
- 升序实现逻辑:名称字段直接返回原值,默认升序排序时就会按字典序从小到大排列,字典序更小的名称优先靠前。
- 效果验证:示例中两个分数为42的条目,对应世界排名分别为650、550,650数值更大,因此
(650, 42, "Namey Name Name")会排在(550, 42, "Namey")前面;如果出现排名、分数完全一致的条目,会自动按名称字典序排序,比如名称为"afirst"的条目会比同名次同分数的"McNamealot"更靠前。
扩展说明
如果需要降序的字段不是数值类型(比如字符串),无法通过取反实现方向反转,可以使用functools.cmp_to_key自定义逐字段比较逻辑,但在当前数值+字符串升序的场景下,上述取反的写法性能最优、代码最简洁。
内容的提问来源于stack exchange,提问作者WPWIV
相关产品推荐
相关产品推荐

