首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何编写降序值排序关键字函数?

如何编写降序值排序关键字函数?
EN

Stack Overflow用户
提问于 2012-06-26 20:00:52
回答 5查看 15.2K关注 0票数 36

在最新版本的Python中,将关键函数从先前的cmp函数传递给sort(),这使得我更难对某些对象执行复杂的排序。

例如,我希望从最新到最旧对一组对象进行排序,其中包含一组字符串附加字段。所以我希望日期的顺序是相反的,但是字符串的顺序是自然的。使用比较函数,我可以将日期字段与字符串字段的比较颠倒过来。但是对于键函数,我需要找到一些方法来反转/反转日期或字符串。

处理数字很容易(虽然很难看)--只需从某些东西中减去它们--但我是否必须为日期找到类似的技巧(从另一个日期中减去它们,然后比较时间增量?)和字符串(...I不知道如何以独立于语言环境的方式颠倒它们的顺序)。

我知道functools.cmp_to_key()的存在,但它被描述为“主要用作转换为Python3的程序的过渡工具,而Python3不再支持比较功能”。这意味着我应该能够用key方法做我想做的事情--但是如何做呢?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2012-06-26 20:42:36

要做到这一点,一种缓慢而优雅的方法是创建一个反向排序的值包装器:

代码语言:javascript
复制
from functools import total_ordering
@total_ordering
class ReversedOrder:
    def __init__(self, value):
        self.value = value
    def __eq__(self, other):
        return other.value == self.value
    def __lt__(self, other):
        return other.value < self.value

如果你没有functools.total_ordering,你将不得不实现所有6个比较,例如:

代码语言:javascript
复制
import operator
class ReversedOrder:
    def __init__(self, value):
        self.value = value
for x in ['__lt__', '__le__', '__eq__', '__ne__', '__ge__', '__gt__']:
    op = getattr(operator, x)
    setattr(ReversedOrder, x, lambda self, other, op=op: op(other.value, self.value))
票数 18
EN

Stack Overflow用户

发布于 2012-06-26 20:26:53

要做到这一点,最通用的方法是简单地依次按每个键分别排序。Python的排序总是稳定的,所以这样做是安全的:

代码语言:javascript
复制
sort(data, key=tiebreakerkey)
sort(data, key=datekey, reverse=True)

将(假设关键函数的相关定义)为您提供按降序日期和升序平局排序的数据。

请注意,这种方式比生成单个组合键函数要慢,因为您最终将执行两个完整的排序,所以如果您可以生成一个组合键,这会更好,但将其拆分成单独的排序可以提供很大的灵活性:给定每个列的一个键函数,您可以对它们进行任意组合,并为任何单独的列指定reverse。

对于完全通用的选项:

代码语言:javascript
复制
keys = [ (datekey, True), (tiebreakerkey, False) ]
for key, rev in reversed(keys):
    sort(data, key=key, reverse=rev)

为了完整性,尽管我真的认为应该尽可能地避免这样做:

代码语言:javascript
复制
from functools import cmp_to_key
sort(data, key=cmp_to_key(your_old_comparison_function))

我认为您应该避免这种情况的原因是,与对关键函数的n调用(或当您进行两次排序时的2n调用)相比,对比较函数的n log n调用。

票数 26
EN

Stack Overflow用户

发布于 2012-06-26 20:41:09

我认为文档不完整。我对“主要”这个词的解释是,仍然有理由使用cmp_to_key,这就是其中之一。尽管key是一个更好的选择,但cmp被移除是因为它是一个“吸引人的麻烦”:人们会被它所吸引。

但是您的情况显然更适合作为cmp函数,所以使用cmp_to_key来实现它。

票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11206884

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档