python3 自定义比较器

部署运行你感兴趣的模型镜像

python3 自带的排序函数 sort()sorted() 等,可以自定义比较器,实现特殊需求,以下介绍3种常见方法。
比如现在有二维空间中的3个点,需要对它们进行排序,规则是:先按x坐标排序,如果相同,则按y坐标排序。

class Pos:
	"""
	坐标类
	"""
    def __init__(self, x = 0, y = 0):
        self.x = x
        self.y = y
         
    def __str__(self):
        return ('(%s, %s)' % (self.x, self.y))

def print_list(l):
	"""
	打印坐标数组
	"""
	print(','.join([str(t) for t in l]))
	

# 待排序的3个坐标,正确的排序结果应该是:(2, 4),(2, 5),(5, 1)
l = [Pos(5, 1), Pos(2,5), Pos(2, 4)]

方法一:自定义比较项

可以通过修改 key= 参数,使用 lambda 将输入的元素映射成一个值,这个值就代表了这个元素的大小。

比如,根据坐标类的比较规则(先比较x再比较y),可以将每个坐标映射成:1000 * x + y,这个值就可以代表这个坐标的大小,容易看出是满足比较规则的(前提条件是 y 不会超过 1000)。

l1 = sorted(l, key=lambda t : 1000 * t.x + t.y)
print_list(l1)

结果为:(2, 4),(2, 5),(5, 1)

方法二:自定义比较方法

可以通过修改 key= 参数,并借助内置的 cmp_to_key ,重写对两个元素的比较方法。

比如,可以直接将坐标的比较规则用代码写出来(可以新建一个函数,也可以直接使用lambda),作为新的比较方法。

from functools import cmp_to_key
def cmp(t1, t2):
    """
    比较函数,需要满足:t1>t2则返回正数,t1=t0则返回0,t1<t2则返回负数。
    """
    if t1.x == t2.x:
        return t1.y - t2.y
    return t1.x - t2.x

# 新建cmp函数    
l2 = sorted(l, key=cmp_to_key(cmp))
print_list(l2)

# 使用lambda
l3 = sorted(l, key=cmp_to_key(lambda a, b : a.x - b.x if a.x != b.x else a.y - b.y))
print_list(l3)

l2l3的结果均为:(2, 4),(2, 5),(5, 1)

方法三:自定义运算符

可以在类中重写比较函数,然后可以直接使用常规的比较运算符来判断两个对象(都属于这个类)的大小。

Python2中可以直接重写__cmp__方法来实现比较,但是Python3中已经取消了,Python3中需要细分每一个比较运算符:

__lt__: <
__gt__: >
__ge__: >=
__eq__: ==
__le__: <=

比如,我们可以在 Pos 类中重写这 5 种方法,作为不同 Pos 之间相互比较的规则。
重新定义 Pos 类:

class Pos:
    def __init__(self, x = 0, y = 0):
        self.x = x
        self.y = y
 
    def __str__(self):
        return ('(%s, %s)' % (self.x, self.y))
 
    def __lt__(self, other):
        return self.x < other.x if self.x != other.x else self.y < other.y
 
    def __gt__(self, other):
        return self.x > other.x if self.x != other.x else self.y > other.y
 
    def __ge__(self, other):
        return self.x >= other.x if self.x != other.x else self.y >= other.y
 
    def __eq__(self, other):
        return self.x == other.x and self.y == other.y
 
    def __le__(self, other):
        return self.x <= other.x if self.x != other.x else self.y <= other.y

这样的话,就可以将 Pos 类当做简单的基本类型数值,可以直接进行比较大小,也适用于所有排序方法。

#测试自定义运算符
print(Pos(5,1) > Pos(2,4)) # 输出 True
print(Pos(5,2) < Pos(5,1)) # 输出 False

# 排序
l4 = sorted(l)
print_list(l4)

结果为:(2, 4),(2, 5),(5, 1)

您可能感兴趣的与本文相关的镜像

Python3.11

Python3.11

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

<think>嗯,用户想了解如何在Python自定义排序比较器。首先,我需要回忆Python中排序相关的知识。记得在Python中,列表有sort()方法,而内置的sorted()函数也可以排序。这两个函数都可以通过key参数来自定义排序的规则。不过,用户提到的是“比较器”,可能是指传统的比较函数,比如其他语言中的Comparator接口。 那Python中的比较器是如何工作的呢?在Python 3之前,sort()和sorted()有一个cmp参数,允许传递一个比较函数。但后来在Python 3中,这个参数被移除了,只能使用key参数。这是因为使用key更高效,因为每个元素只需要处理一次,而cmp需要多次比较,效率较低。 所以用户可能需要知道两种方法:一种是使用key参数,另一种是在需要cmp的情况下如何转换。比如,使用functools中的cmp_to_key函数比较函数转换成key函数。 接下来,我需要整理步骤。首先,说明基本用法,使用key参数。例如,sorted(list, key=lambda x: x%10)会按个位数排序。然后,如果需要更复杂的比较逻辑,比如先按长度再按字母顺序排序字符串,可以用key返回元组,如key=lambda s: (len(s), s)。 然后,当用户确实需要比较函数时,比如自定义比较两个元素的逻辑,就需要用到cmp_to_key。这时候需要导入functools中的cmp_to_key,然后将比较函数传入key参数。比较函数应该接受两个参数,返回负数、零或正数,表示第一个参数应该排在前面、相等还是后面。 例如,想要逆序排列数字,可以定义比较函数def compare(a, b): return b - a,然后用sorted(nums, key=cmp_to_key(compare))。 需要提醒用户注意,Python 3中不再支持cmp参数,必须用key,并且使用cmp_to_key可能会有性能损失,因此推荐优先使用key函数。 另外,可能需要举例说明两者的区别和应用场景。比如,当排序规则无法通过单一键值表达时,比如需要根据多个条件动态比较,这时候可能需要比较函数。 最后,总结步骤和注意事项,确保用户理解如何正确应用这些方法。</think>在 Python自定义排序比较器主要通过以下两种方式实现,以下是详细说明和示例: --- ### 方法 1:使用 `key` 参数(推荐) 这是 Python 3 中主要推荐的方式,通过为每个元素生成一个**排序键值**来决定顺序。 #### 基本语法 ```python sorted_list = sorted(iterable, key=key_function) list.sort(key=key_function) ``` #### 示例 1:按字符串长度排序 ```python words = ["apple", "banana", "cherry", "date"] sorted_words = sorted(words, key=lambda x: len(x)) # 输出:[&#39;date&#39;, &#39;apple&#39;, &#39;banana&#39;, &#39;cherry&#39;] ``` #### 示例 2:按元组多条件排序 ```python students = [ ("Alice", 22, 90), ("Bob", 20, 85), ("Charlie", 22, 88) ] # 按年龄升序,分数降序 sorted_students = sorted(students, key=lambda x: (x[1], -x[2])) ``` --- ### 方法 2:使用 `cmp_to_key`(传统比较函数) 当需要更复杂的比较逻辑时(例如需要同时访问两个元素),可以使用 `functools.cmp_to_key` 将传统比较函数转换为 key 函数。 #### 步骤 1. 定义比较函数:接受两个参数,返回: - 负数:`a` 应排在 `b` 前 - 正数:`b` 应排在 `a` 前 - 零:两者等价 2. 使用 `cmp_to_key` 转换: ```python from functools import cmp_to_key def compare(a, b): if 自定义条件: return -1 # a 排在前面 elif 另一条件: return 1 # b 排在前面 else: return 0 sorted_list = sorted(iterable, key=cmp_to_key(compare)) ``` #### 示例:自定义逆序排序 ```python from functools import cmp_to_key nums = [3, 1, 4, 1, 5] def reverse_compare(a, b): return b - a # 返回正数时 b 排在 a 前 sorted_nums = sorted(nums, key=cmp_to_key(reverse_compare)) # 输出:[5, 4, 3, 1, 1] ``` --- ### 关键区别 | 特性 | `key` 参数 | `cmp_to_key` | |--------------------|-------------------------------|----------------------------------| | 性能 | 更高(每个元素计算一次键值) | 更低(每次比较需计算) | | Python 3 兼容性 | ✅ 原生支持 | ✅ 需通过 `functools` 转换 | | 适用场景 | 单维度或多维度静态规则 | 动态依赖两个元素的复杂比较逻辑 | --- ### 最佳实践建议 1. **优先使用 `key` 参数**:性能更高,代码更简洁。 2. 对多条件排序,可以返回元组作为键值: ```python key=lambda x: (x.条件1, -x.条件2) # 条件1升序,条件2降序 ``` 3. 仅当无法用 `key` 表达逻辑时(如需要比较两个元素的关联性),才使用 `cmp_to_key`。 --- 通过灵活组合这些方法,可以实现任意复杂的排序需求。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值