自定义Python列表排序


93

我重构了我的一些旧代码,发现了这一点:

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()用来实现自定义排序。有人可以解释为什么这样做吗?


sorted()sort()以几乎相同的方式提供自定义排序,对调用约定的差异取模。
罗素·博罗戈夫

2
确实,发生的事情是使用key参数胜过传递 cmp函数。(后者甚至没有在Python 3中实现)
jsbueno 2012年

这有点模棱两可,取决于列表中的内容。您的代码要求它们具有属性foo,否则它会崩溃。更好地定义一个自定义__lt__()的方法为您的类,然后sorted()list.sort()将工作外的开箱。(顺便说一句,对象不再需要定义__cmp__(),只是__lt__()请参阅本
SMCI

Answers:


60

它记录在这里

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

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


谢谢miles82,我在这里检查,在方法签名docs.python.org/tutorial/datastructures.html中看
Lorenzo

在您链接到的页面上看不到相同的文本。文档是否有所更改。此外,当我尝试使用时cmp,我会得到TypeError: 'cmp' is an invalid keyword argument for this function。这里发生了什么?
HelloGoodbye

1
@HelloGoodbye sort()在Python 3中没有cmp参数。当docs链接用于Python 2时,这是一个旧答案。您可以在此处找到旧文档在此处了解更多信息。如果您使用的是Python 3,请改用key参数
miles82

如果您真的想提供比较功能呢?我想将字符串(任意长度,贪婪地挑选出来)中的数字视为符号,等效于如何处理单个字符。如果可以提供比较功能,但如果必须提供关键功能,我知道如何轻松地实现这一目标。为什么改变了?
HelloGoodbye

我想如果字符串中包含的每个数字都使用按字典顺序对数字进行排序的编码(例如Levenshtein编码)仍然可以实现。但是,我认为这更多是针对以下事实的变通方法:sort在Python 3中,比较函数不将比较函数作为参数,而不是我实际上想做的事情。
HelloGoodbye

104

附带说明一下,这是实现相同排序的更好的选择:

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

或者:

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

查看如何排序非常有用。


1
TIL关于运算符,非常有用。
2015年

13

就像这个例子。您要对该列表进行排序。

[('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

最后:

只是 sort(letter_cmp)


4
它如何知道要排序的列表?
卡梅隆僧侣

2
@CameronMonks yourList.sort(letter_cmp)
Minyc510

7

这在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)

1

在python3中,您可以编写:

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

alist = sorted(alist, key=cmp_to_key(cmp_items))

0

更好的是:

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.