部分键的反向排序顺序

Reverse sort order for part of a key

我需要对对象列表进行排序。目前我是这样做的:

mylist = [aobject, bobject, cobject]
mylist.sort(key=mykey)
def mykey(sortelem):
    attribute1 = sortelem.attribute1
    attribute2 = sortelem.attribute2
    return (attribute1, attribute2)

现在我想按 attribute1 升序排序,但 attribute2 降序排序。我总是可以做这样的事情:

return (attribute1, -1 * attribute2)

但这似乎很不符合Python。我已经在网上搜索过了,但是很难搜索到。

TL;DR:您可以排序两次,在需要的地方添加一个 reversed=True 参数。首先按决胜局排序。这是有效的,因为排序在 Python.

中是稳定的

在元组中使用 - attribute2 而不是 attribute2 是最简单的方法 如果 attribute2 是一个数字。

如果 attribute2 是一个字符串,或者其他不能以有意义的方式与 -1 相乘的东西,那么这个技巧就不起作用。

但是请注意,lst.sortsorted在python中保证是stable sorts。特别是,这意味着以下两个代码片段是等效的:

# SORT ACCORDING TO A TUPLE
l.sort(key=lambda x: (x[0], x[1]))

# SORT TWICE
l.sort(key=lambda x: x[1])
l.sort(key=lambda x: x[0])

请注意在第二个版本中,我们首先按 tie-breaker 排序,然后按主要标准排序。

对于第一个版本,我们可以通过将两个标准中的一个乘以 -1 来按降序排序,如果这个标准是数字的话:

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

然而,对于第二个版本,我们可以使用可选参数 reverse=True 按两个标准之一的降序排序,这适用于数字以及其他类型,例如字符串。

l.sort(key=lambda x: x[1], reverse=True)
l.sort(key=lambda x: x[0])

最后,请注意,您可以使用 operator.itemgetteroperator.attrgetter,而不是使用 deflambda 定义自定义函数作为排序键。 =29=]

例如,下面两个代码片段是等价的:

# FIRST VERSION
l.sort(key=lambda x: (x[0], x[1]))

# SECOND VERSION
from operator import itemgetter
l.sort(key=itemgetter(0, 1))

以下三个代码片段是等价的:

# FIRST VERSION
def mykey(x):
    x1 = x.attribute1
    x2 = x.attribute2
    return (x1, x2)
l.sort(key=mykey)

# SECOND VERSION
l.sort(key=lambda x: (x.attribute1, x.attribute2))

# THIRD VERSION
from operator import attrgetter
l.sort(key=attrgetter('attribute1', 'attribute2'))