60

可能重复:
如何为降序值编写 Python 排序键函数

在 Python 3 中,使用多个键按字典顺序对对象列表进行排序非常容易。例如:

items.sort(key = lambda obj: obj.firstname, obj.lastname)

reverse参数允许您指定是升序还是降序。但是,如果您想按多个键排序,但您想对第一个键使用降序排序,而对第二个键使用升序排序,您会怎么做?

例如,假设我们有一个具有两个属性的对象,points并且name,其中points是一个int,并且name是一个str。我们希望按降序对这些对象的列表进行排序points以便具有最多点数的对象排在第一位),但是对于具有相同数量的对象points,我们希望name按字母(升序)顺序对这些对象进行排序。

如何做到这一点?

4

3 回答 3

38

没有内置的方法来处理这个问题。对于一般情况,您必须排序两次:首先按次要排序,然后按主要排序。正如@Mark Ransom 在他的评论中提到的那样,在许多情况下变量是数字的,因此您可以使用负值来翻转排序。

如果您知道要排序的变量的类型以及如何使用它,您还可以编写一个 key 函数,该函数为递增的键返回一个递减的值。有关字符串的示例,请参见此线程。(基本上,你取字符的 ASCII 数值的负数。)

在 Python 2 中,您还可以使用cmp函数而不是键,但这可能会使排序变慢。它是否会使它变得太慢取决于列表的大小和未排序的大小。在 Python 3 中,该cmp参数已经消失,但正如@Mark Ransom 所说,您可以使用cmp_to_key.

于 2012-07-13T18:52:39.467 回答
16
items.sort(key = lambda obj: (obj.firstname, [(-ord(c) for c in obj.lastname)]))
于 2012-07-13T19:47:20.807 回答
8

将比较functools.cmp_to_key函数转换为与排序函数兼容的键。这是为在 Python 2 中使用比较函数并需要转换为不再允许它们的 Python 3 的排序提供的。

编辑:Python wiki 中的“排序稳定性”和“复杂排序”标题下还有一个建议,可以从最不重要的关键到最重要的多遍进行排序。之所以可行,是因为 Python 的排序保证是稳定的,因此在遇到等效键时会保持先前的顺序。

于 2012-07-13T18:53:59.440 回答