使用比较器功能进行排序

时间:2012-10-05 15:26:51

标签: python

所以我使用一些预先存在的比较器来比较两个元组中的某些值,如果第一个大于第二个,则返回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

现在,我有一个字典,其上面有许多类型的元组条目。我想以相反的顺序对它们进行排序,但我真的不明白我将如何实现这一目标。我想的是:

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

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

2 个答案:

答案 0 :(得分:29)

您将比较器作为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)

(虽然实际上,你应该使用关键功能:

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

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

答案 1 :(得分:13)

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

According to the docs,签名现在为sorted(iterable, *, key=None, reverse=False),因此您必须使用key函数进行自定义排序。文档建议:

使用functools.cmp_to_key()将老式的 cmp 函数转换为 key 函数。

这是一个例子:

>>> 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)]

但是,您的函数也不符合旧的 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

然后您可以做:

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