111

我正在重构我的一些旧代码并遇到了这个问题:

alist.sort(cmp_items)

def cmp_items(a, b):
    if a.foo > b.foo:
        return 1
    elif a.foo == b.foo:
        return 0
    else:
        return -1

该代码有效(我在大约 3 年前编写了它!)但是我在 Python 文档的任何地方都找不到这个东西,每个人都用它sorted()来实现自定义排序。有人可以解释为什么这有效吗?

4

6 回答 6

122

作为旁注,这是实现相同排序的更好选择:

alist.sort(key=lambda x: x.foo)

或者:

import operator
alist.sort(key=operator.attrgetter('foo'))

查看排序方法,它非常有用。

于 2012-08-07T16:49:06.373 回答
66

它记录在这里

sort() 方法采用可选参数来控制比较。

cmp 指定两个参数(列表项)的自定义比较函数,该函数应返回负数、零或正数,具体取决于第一个参数被认为小于、等于还是大于第二个参数: cmp=lambda x,y : cmp(x.lower(), y.lower())。默认值为无。

于 2012-08-07T16:44:47.610 回答
26

就像这个例子一样。你想对这个列表进行排序。

[('c', 2), ('b', 2), ('a', 3)]

输出:

[('a', 3), ('b', 2), ('c', 2)]

您应该按第二项对元组进行排序,然后是第一项:

def letter_cmp(a, b):
    if a[1] > b[1]:
        return -1
    elif a[1] == b[1]:
        if a[0] > b[0]:
            return 1
        else:
            return -1
    else:
        return 1

然后将其转换为关键函数:

from functools import cmp_to_key
letter_cmp_key = cmp_to_key(letter_cmp))

现在您可以使用自定义排序顺序:

[('c', 2), ('b', 2), ('a', 3)].sort(key=letter_cmp_key)
于 2016-03-18T03:26:22.477 回答
14

这在 Python 3 中不起作用。

您可以使用 functools cmp_to_key 让旧式比较函数工作。

from functools import cmp_to_key

def cmp_items(a, b):
    if a.foo > b.foo:
        return 1
    elif a.foo == b.foo:
        return 0
    else:
        return -1

cmp_items_py3 = cmp_to_key(cmp_items)

alist.sort(cmp_items_py3)
于 2018-08-06T12:41:35.323 回答
12

我知道很多人已经发布了一些很好的答案。但是,我想建议一种无需导入任何库的好方法。

l = [(2, 3), (3, 4), (2, 4)]
l.sort(key = lambda x: (-x[0], -x[1]) )
print(l)
l.sort(key = lambda x: (x[0], -x[1]) )
print(l)

输出将是

[(3, 4), (2, 4), (2, 3)]
[(2, 4), (2, 3), (3, 4)]

输出将根据我们以元组格式提供的参数的顺序进行排序

于 2020-10-13T05:49:23.803 回答
3

更好的是:

student_tuples = [
    ('john', 'A', 15),
    ('jane', 'B', 12),
    ('dave', 'B', 10),
]

sorted(student_tuples, key=lambda student: student[2])   # sort by age
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]

取自:https ://docs.python.org/3/howto/sorting.html

于 2020-08-01T15:52:23.607 回答