按元组第二个值降序和第一个值升序排序列表

42 投票
3 回答
59492 浏览
提问于 2025-04-17 13:22

我需要对一个字典进行排序,首先是根据值进行排序,使用 reverse=True,也就是说要把值大的排在前面;如果有重复的值,就要根据键进行排序,这时使用 reverse=False,也就是把键小的排在前面。

到目前为止,我有这个:

dict = [('B', 3), ('A', 2), ('A', 1), ('I', 1), ('J', 1)]
sorted(dict.items(), key=lambda x: (x[1],x[1]), reverse=True)

这个返回了...

[('B', 3), ('A', 2), ('J', 1), ('I', 1), ('A', 1)]

但我需要的是:

[('B', 3), ('A', 2), ('A', 1), ('I', 1), ('J', 1)]

如你所见,当值相等时,我只能按照指定的方式让键降序排列...但是我该如何让它们按升序排列呢?

3 个回答

2

你可以使用 collections.defaultdict

In [48]: from collections import defaultdict

In [49]: dic=[('B', 3), ('A', 2), ('A', 1), ('I', 1), ('J', 1)]

In [50]: d=defaultdict(list)

In [51]: for x,y in dic:
    d[y].append(x)
    d[y].sort()          #sort the list

现在 d 看起来像这样:

 defaultdict(<type 'list'>, {1: ['A', 'I', 'J'], 2: ['A'], 3: ['B']}

也就是说,这是一个新的 dict,它的键是 1,2,3...,对应的值是存储在列表中的字母。

现在你可以通过 sorted(d.items) 来遍历这个字典,并使用 itertools.chain()itertools.product() 来得到你想要的结果。

In [65]: l=[ product(y,[x]) for x,y in sorted(d.items(),reverse=True)]

In [66]: list(chain(*l))
Out[66]: [('B', 3), ('A', 2), ('A', 1), ('I', 1), ('J', 1)]
5

在编程中,有时候我们会遇到一些问题,可能是因为代码写得不够清晰,或者是我们对某个概念理解得不够透彻。比如说,有人可能在使用某个函数时,不太明白它的作用或者用法。这种情况下,查看相关的讨论或者提问是很有帮助的。

在StackOverflow上,很多人会分享他们的经验和解决方案。你可以看到不同的观点和方法,这样可以帮助你更好地理解问题所在。记得多看看别人的代码和解释,慢慢你就会掌握这些知识。

总之,遇到问题不要怕,积极寻求帮助和学习,编程的路上总会有新的发现和成长。

In [4]: l = [('B', 3), ('A', 2), ('A', 1), ('I', 1), ('J', 1)]

In [5]: sorted(l, key=lambda (x,y):(-y,x))
Out[5]: [('B', 3), ('A', 2), ('A', 1), ('I', 1), ('J', 1)]
69

下面的代码可以处理你的输入:

d = [('B', 3), ('A', 2), ('A', 1), ('I', 1), ('J', 1)]
sorted(d,key=lambda x:(-x[1],x[0]))

因为你的“值”是数字,所以你可以通过改变符号来轻松反转排序顺序。

换句话说,这种排序方式是先根据值来排序(-x[1]),负号的作用是把大的数字排在前面;如果有数字相同的情况,就根据键(x[0])来排序。

如果你的值不能简单地通过“取反”来让大的项目排在前面,还有一个简单的解决办法就是排序两次:

from operator import itemgetter
d.sort(key=itemgetter(0))
d.sort(key=itemgetter(1),reverse=True)

这样做是有效的,因为Python的排序是稳定的。

撰写回答