【问题标题】:Sort by multiple keys using different orderings [duplicate]使用不同的顺序按多个键排序[重复]
【发布时间】:2012-07-14 03:47:20
【问题描述】:

可能重复:
How to write Python sort key functions for descending values

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

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

reverse 参数可让您指定是升序还是降序。但是,如果您想按多个键排序,但又想对第一个键使用降序排序,而对第二个键使用升序排序,该怎么办?

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

如何做到这一点?

【问题讨论】:

  • Ints 是一种特殊情况,因为您可以只使用负数来获得反向排序。我会对它们都是字符串的情况更感兴趣。

标签: python python-3.x


【解决方案1】:

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

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

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

【讨论】:

  • 很好的答案,但是 cmp 在 python3 中不再存在(我认为)。
  • 你说得对,我没有注意到这个问题是专门关于 Python 3 的。我编辑了我的答案。
【解决方案2】:
items.sort(key = lambda obj: (obj.firstname, [(-ord(c) for c in obj.lastname)]))

【讨论】:

【解决方案3】:

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

编辑:Python wiki 中的标题 Sort Stability and Complex Sorts 下还有一个建议,可以从最不重要的键到最重要的键多次进行排序。之所以可行,是因为 Python 的排序保证是稳定的,因此在遇到等效键时会保持之前的顺序。

【讨论】:

  • 感谢您的建议,稳定排序允许在多次迭代中执行复杂排序。有趣的是它并不比使用 2.x cmp 慢。我相信在大多数复杂的情况下, cmp 会很好,并且它的删除是一个错误。我害怕使用 cmp_to_key 因为谁知道它也可能在某个时候被丢弃。
猜你喜欢
  • 1970-01-01
  • 2013-09-16
  • 1970-01-01
  • 1970-01-01
  • 2015-04-07
  • 2015-08-25
  • 1970-01-01
  • 2014-08-02
  • 2023-03-04
相关资源
最近更新 更多