首页 > 解决方案 > 在排序期间使用多个字段进行键评估的pythonic方法是什么?

问题描述

Python3 去掉了排序时用来比较的cmp参数,取而代之的是key.

引入该cmp_to_key函数是为了“主要用作从 Python 2 转换的程序的转换工具”。

我不清楚如何cmp在 python3 中使用key. 例如,如果我想按长度对字符串进行排序,并按字典顺序使用决胜局,我会这样写:

def compare(word1, word2):
    if len(word1) > len(word2):
        return 1
    if len(word2) > len(word1):
        return -1
    if word1 < word2:
        return 1
    if word2 < word1:
        return -1
    return 0

myStrings.sort(key=functools.cmp_to_key(compare), reverse=True)

如何以python3-native方式进行对象之间的比较,意思是没有cmp_to_key

我能想到的一件事是返回一个更复杂的密钥,例如:

# This would return something like 5.12 for "hello" and 5.20 for "world"
def myKey(word):
    return len(word) + myLexicographicalValueFunction(word)/100

myStrings.sort(key=myKey, reverse=True)

但是,当您添加更多变量进行比较时,这似乎并不能很好地扩展。在python3中排序期间使用多个字段进行键评估的pythonic方法是什么?

标签: pythonpython-3.x

解决方案


对于该特定比较,您可以使用元组作为键:

myStings.sort(key=lambda s:(-len(s),s),reverse=True)

对于对象类,您可能需要实现一个比较运算符(例如def __lt__(self,other):方法)来让排序知道如何在本地比较它们。

如果您无法修改对象类或者您的比较非常复杂,您可以创建一个包装器对象,该对象__lt__()使用您提供的 lambda 实现该方法:

class ObjectComp:
    def __init__(self,instance,cmp):
        self.instance = instance
        self.cmp      = cmp
        
    def __lt__(self,other):
        return self.cmp(self.instance,other.instance)
        
def cmpsort(objects,cmp):
    return [obj.instance for obj in sorted(ObjectComp(o,cmp) for o in objects)]


s = cmpsort([1,11,21,12,13],cmp=lambda a,b:a%10>b%10)
print(s)
[13, 12, 1, 11, 21]

推荐阅读