使用比较器功能进行排序

use*_*661 24 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
Run Code Online (Sandbox Code Playgroud)

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

sortedDict = sorted(subjects, key=comparator, reverse = True)
Run Code Online (Sandbox Code Playgroud)

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

Fre*_*Foo 34

你将比较器作为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)
Run Code Online (Sandbox Code Playgroud)

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

sorted(subjects, operator.itemgetter(0), reverse=True)
Run Code Online (Sandbox Code Playgroud)

另请注意,sortedDict实际上并不是一个dict,所以名称相当混乱.)

  • 此外,比较器不应返回"True"或"False",而应返回-1,0或1. (8认同)
  • 对比较器的包装函数做了很好的工作.你也可以提一下`functools.cmp_to_key`. (4认同)
  • `functools.cmp_to_key`可用于此类事情 (4认同)
  • 请注意,这是**弃用**。请参阅@IgnacioVazquez-Abrams 或我在问题评论中的回答。 (2认同)

kay*_*ya3 34

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

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

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

下面是一个例子:

>>> 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)]
Run Code Online (Sandbox Code Playgroud)

但是,您的函数也不符合旧的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
Run Code Online (Sandbox Code Playgroud)

然后你可以这样做:

>>> your_key = cmp_to_key(predicate_to_cmp(cmpValue))
>>> sorted(data, key=your_key)
[(1, None), (2, None), (3, None), (4, None)]
Run Code Online (Sandbox Code Playgroud)


Tua*_*hau 5

@kaya3的答案是正确的。我只是提出另一种实现,我们可以使用布尔值作为比较器。

class YourTupleComparator(tuple):
    def __lt__(self, other):
        return self[0] < other[0]

sorted(subjects, key=YourTupleComparator)
Run Code Online (Sandbox Code Playgroud)