tuoheng_algN/test/偏函数/cmp_to_key.py

51 lines
2.6 KiB
Python
Raw Normal View History

2025-01-21 09:26:34 +08:00
"""
python标准模块functools中的cmp_to_key可以将一个cmp函数变成一个key函数从而支持自定义排序
python的列表提供了sort方法下面是该方法的一个示例
"""
lst = [(9, 4), (2, 10), (4, 3), (3, 6)]
lst.sort(key=lambda item: item[0])
print(lst)
"""
sort方法的key参数需要设置一个函数这个函数返回元素参与大小比较的值这看起来没有问题但如果想实现更加复杂的自定义排序就不那么容易了
目前的排序规则是根据元组里第一个元素的大小进行排序我现在修改规则如果元组里第一个元素是奇数就用元组里第一个元素进行排序
如果元组里第一个元素是偶数则用这个元组里的第二个元组进行大小比较面对这样的需求列表的sort方法无法满足
对于这种情形可以使用functools.cmp_to_key来解决
"""
from functools import cmp_to_key
lst = [(9, 4), (2, 10), (4, 3), (3, 6)]
def cmp(x, y):
a = x[0] if x[0] % 2 == 1 else x[1]
b = y[0] if y[0] % 2 == 1 else y[1]
return 1 if a > b else -1 if a < b else 0
lst.sort(key=cmp_to_key(cmp))
print(lst)
# 仍然使用sort进行排序我实现了一个cmp函数该函数实现了需求中所提到的要求该函数最终要返回两个元组比较的大小关系其实cmp_to_key的实现非常简单
def cmp_to_key(mycmp):
"""Convert a cmp= function into a key= function"""
class K(object):
__slots__ = ['obj']
def __init__(self, obj):
self.obj = obj
def __lt__(self, other):
return mycmp(self.obj, other.obj) < 0
def __gt__(self, other):
return mycmp(self.obj, other.obj) > 0
def __eq__(self, other):
return mycmp(self.obj, other.obj) == 0
def __le__(self, other):
return mycmp(self.obj, other.obj) <= 0
def __ge__(self, other):
return mycmp(self.obj, other.obj) >= 0
__hash__ = None
return K
"""
它在内部定义了一个类K 并使用我传入的cmp函数完成了比较关系运算符的重载函数返回的是一个类而sort函数的key需要的是一个函数
看起来矛盾但在python中这样做完全可行因为类和函数都是callable的这里把类当成了函数来用
在本篇第一段代码中
lst.sort(key=lambda item: item[0])
lambda表达式生成的匿名函数返回的是元组的第一个元素进行大小比较而现在cmp_to_key返回的是类K参与比较的是K的对象
由于K已经实现了比较关系运算符重载且算法就是我刚刚实现的cmp函数这样就最终实现了自定义排序
"""