将比较器作为Python 3中的键进行排序的正确方法是什么?

Nin*_*ner 8 python sorting python-3.x

我不确定如何在Python 3中编写比较器,因为cmp参数已被删除.考虑到Python 3中的以下代码,如何仅使用密钥重写比较器?

import functools

def my_cmp(x, y):
    return x*5-y*2

l = [50, 2, 1, 9]
print(sorted(l, key=functools.cmp_to_key(my_cmp)))
Run Code Online (Sandbox Code Playgroud)

谢谢.

alf*_*sin 3

您提出的这个“比较”函数是不一致的:它应该提供明确的(确定性)顺序,这意味着,如果您更改列表中元素的顺序并运行sorted- 您应该得到相同的结果!

在您的情况下,元素的顺序会影响排序:

import functools

def my_cmp(x, y):
    return x*5-y*2


l = [50, 2, 1, 9]
print(sorted(l, key=functools.cmp_to_key(my_cmp))) # [2, 1, 9, 50]

l = [50, 1, 2, 9]
print(sorted(l, key=functools.cmp_to_key(my_cmp))) # [1, 2, 9, 50]
Run Code Online (Sandbox Code Playgroud)

这意味着你的“比较”功能不一致。首先提供良好的排序函数,那么将其转换为函数应该不会很困难key


关于您在评论中提出的问题,key接受一个仅接受单个参数的函数 - 并返回“它有多大”的“测量值”。最简单的例子是比较数字,在这种情况下,您的关键功能可以简单地是:lambda x: x。对于任何数字,lambda 表达式都会返回自身,并且现在比较变得微不足道!

修改你的例子:

def my_key(x):
    return x    

l = [50, 2, 1, 9]
print(sorted(l, key=my_key)) # [1, 2, 9, 50]
Run Code Online (Sandbox Code Playgroud)

上述内容的较短版本是:

l = [50, 2, 1, 9]
print(sorted(l, key=lambda x: x)) # [1, 2, 9, 50]
Run Code Online (Sandbox Code Playgroud)

  • @LukeDupin `key=lambda x: x.scope, x.type, x.status, x.name` 它返回一个元组,其中字段按您希望的顺序排序,并按字母顺序(字典)在元组之间进行比较。很好吧? (6认同)
  • 简单的用例;你有一个对象,有 4 个变量。3个是整数,称它们为(范围、类型、状态),最后一个变量是名称、字符串。想要按范围组排序,然后键入,然后按状态,然后按字母顺序排序,这没有任何问题。这可以用 cmp 清楚地编写和维护。然而,密钥需要破解,或多级数组/散列才能完成。我的密钥没有任何问题,但删除 cmp 时遇到了很大的问题。我很欣赏你的谦虚意见,但关键是有限的,不是以健康的方式。 (3认同)
  • “排序”功能在这里无关紧要。它仅用于演示目的,很可能是 (x*3.14+y*2.71) 。我只想知道在 Python 3 中编写可以比较 2 个值的“cmp”函数的正确方法是什么。 (2认同)