Python 使用比较器功能进行排序

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12749398/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 11:46:32  来源:igfitidea点击:

Using a comparator function to sort

pythonsortingcomparator

提问by user1427661

So I'm working with a few pre-existing comparators that compare certain values in two tuples and return true if the first is greater than the second, false if otherwise. Here's the code for one of them:

所以我正在使用一些预先存在的比较器,它们比较两个元组中的某些值,如果第一个大于第二个则返回 true,否则返回 false。这是其中之一的代码:

def cmpValue(subInfo1, subInfo2):
    """
    Returns True if value in (value, work) tuple subInfo1 is GREATER than
    value in (value, work) tuple in subInfo2
    """
    # TODO...
    if subInfo1[0] > subInfo2[0]:
        return True
    else:
        return False

Now, I have a dictionary that has numerous tuple entries of the type being compared above. I want to sort them all in reverse order, but I don't really understand how I would accomplish that. I was thinking something like:

现在,我有一本字典,其中包含许多上面比较的类型的元组条目。我想以相反的顺序对它们进行排序,但我真的不明白我将如何做到这一点。我在想这样的事情:

sortedDict = sorted(subjects, key=comparator, reverse = True)

But I don't know what to pass into the comparator because each comparator takes two arguments (subInfo1, subInfo2). I cannot change the comparator functions.

但是我不知道要传递给比较器的内容是什么,因为每个比较器都有两个参数(subInfo1、subInfo2)。我无法更改比较器功能。

采纳答案by Fred Foo

You're passing the comparator as the keyfunction. You should be passing it as the cmp, wrapped in some kind of function that turns it into a proper comparator.

您将比较器作为key函数传递。您应该将它作为cmp, 包装在某种函数中,将其转换为适当的比较器。

def make_comparator(less_than):
    def compare(x, y):
        if less_than(x, y):
            return -1
        elif less_than(y, x):
            return 1
        else:
            return 0
    return compare

sortedDict = sorted(subjects, cmp=make_comparator(cmpValue), reverse=True)

(Although actually, you should be using key functions:

(尽管实际上,您应该使用关键功能:

sorted(subjects, operator.itemgetter(0), reverse=True)

Also note that sortedDictwill not actually be a dict, so the name is rather confusing.)

另请注意,sortedDict实际上不会是 a dict,因此名称相当混乱。)

回答by kaya3

In Python 3 there is no cmpargument for the sortedfunction (nor for list.sort).

在 Python 3cmp中,sorted函数没有参数(也没有 for list.sort)。

According to the docs, the signature is now sorted(iterable, *, key=None, reverse=False), so you have to use a keyfunction to do a custom sort. The docs suggest:

根据 docs,签名现在是sorted(iterable, *, key=None, reverse=False),所以你必须使用一个key函数来进行自定义排序。文档建议:

Use functools.cmp_to_key()to convert an old-style cmpfunction to a keyfunction.

functools.cmp_to_key()一个老式的转换CMP功能的关键功能。

Here's an example:

下面是一个例子:

>>> def compare(x, y):
...     return x[0] - y[0]
... 
>>> data = [(4, None), (3, None), (2, None), (1, None)]
>>> from functools import cmp_to_key
>>> sorted(data, key=cmp_to_key(compare))
[(1, None), (2, None), (3, None), (4, None)]

However, your function doesn't conform to the old cmpfunction protocol either, since it returns Trueor False. To convert cmpValueinto the appropriate form, you can do:

但是,您的函数也不符合旧的cmp函数协议,因为它返回TrueFalse。要转换cmpValue为适当的形式,您可以执行以下操作:

def predicate_to_cmp(predicate):
    def cmp(x, y):
        if predicate(x, y):
            return 1
        elif x == y:
            return 0
        else:
            return -1
    return cmp

Then you can do:

然后你可以这样做:

>>> your_key = cmp_to_key(predicate_to_cmp(cmpValue))
>>> sorted(data, key=your_key)
[(1, None), (2, None), (3, None), (4, None)]