如何按照相反顺序对元组进行排序,同时打破非相反顺序的关系?(Python)

11
如果我有一个元组列表:
results = [('10', 'Mary'), ('9', 'John'), ('10', 'George'), ('9', 'Frank'), ('9', 'Adam')]

如何对列表进行排序,使得按分数从高到低排序,但相同分数的情况下按姓名字母顺序排序?

排序后,该列表应该如下所示:

results = [('10', 'George'), ('10', 'Mary'), ('9', 'Adam'), ('9', 'Frank'), ('9', 'John')]

目前我能做的只有 results.sort(reverse=True),但它也会以反向字母顺序打破相同的情况...

任何帮助都将不胜感激。谢谢!


1
"'10' < '9' is True" 和 "'Adam' < 'Frank' is True"。我猜你想说的是 "'10' > '9'"? - Kabie
为什么你用字符串代替整数来表示数字? - user2357112
这是一个很好的观点!我没有考虑到那一点。现在我的所有数字都是整数,但我仍然不确定如何进行反向排序和打破非反向的绑定... - chillman
4个回答

24

实现您想要的最简单的方法是利用Python排序是稳定的这一事实。这允许先按字母顺序排序,然后再按分数排序:

In [11]: results = [(10, 'Mary'), (9, 'John'), (10, 'George'), (9, 'Frank'), (9, 'Adam')]

In [12]: results.sort(key=lambda x: x[1])

In [13]: results.sort(key=lambda x: x[0], reverse=True)

In [14]: results
Out[14]: [(10, 'George'), (10, 'Mary'), (9, 'Adam'), (9, 'Frank'), (9, 'John')]

第一种排序方式按字母顺序升序排序。第二种排序方式按分数降序排序,保持相等分数元素的相对顺序。

您可以使用这种方法进行更复杂的排序。只需记住,必须首先按照次要关键字排序,然后再按照第一个关键字排序。(如果您有三个关键字,则首先按第三个排序,然后按第二个排序,最后按主要关键字排序)。

如果您不想调用sort两次,则需要编写更复杂的key函数。例如:

In [50]: def key(elem):
    ...:     return elem[0], [-ord(c) for c in elem[1]]

In [51]: sorted(results, key=key, reverse=True)
Out[51]: [(10, 'George'), (10, 'Mary'), (9, 'Adam'), (9, 'Frank'), (9, 'John')]

具体而言,每当您有按字典顺序排序的东西(例如字符串、元组、列表等)时,您可以通过将所有元素的符号更改为倒转排序。


2
值得注意的是,您可以通过使用默认的升序排序并反转数字而避免在“一次排序调用”示例中的某些复杂性,而不是字符串sorted(results, key=lambda x: (-x[0], x[1])) - Daniel

7

sort方法接受可选的key参数。

key指定了一个只有一个参数的函数,用于从每个列表元素中提取比较键。

您需要将字符串转换为数字:

>>> results = [('10', 'Mary'), ('9', 'John'), ('10', 'George'), ('9', 'Frank'), ('9', 'Adam')]
>>> results.sort(key=lambda x: (int(x[0]), x[1]), reverse=True)
>>> results
[('10', 'Mary'), ('10', 'George'), ('9', 'John'), ('9', 'Frank'), ('9', 'Adam')]

1
你可以使用sort方法的key参数来对元组中的每个值进行排序,并且可以非常精细地控制。例如:
In [41]: results = [('10', 'Mary'), ('9', 'John'), ('10', 'George'), ('9', 'Frank'), ('9', 'Adam')]

In [42]: results.sort(key=lambda (score, name): (-int(score), name))

In [43]: results
Out[43]: 
[('10', 'George'),
 ('10', 'Mary'),
 ('9', 'Adam'),
 ('9', 'Frank'),
 ('9', 'John')]

-1

只需使用sorted即可。

>>> sorted(results)
[('10', 'George'), ('10', 'Mary'), ('9', 'Adam'), ('9', 'Frank'), ('9', 'John')]

默认的cmp函数通过按顺序比较元组的每个成员(从0到n)来检查元组的优先级。


啊,我明白了——问题在于如果数字是其他任何东西,这个方法就行不通了……我想这只是一个糟糕的例子 :) 抱歉。 - chillman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接