假设我有一个比较器,它使用比较的两个值来确定排序。
例如,在this problem中,我们必须使用同时使用两个元素的比较器函数:
def comparator(a, b):
ab = str(a) + str(b)
ba = str(b) + str(a)
return ((int(ba) > int(ab)) - (int(ba) < int(ab)))
排序时可以用key=lambda x: ...
格式写吗?
我知道存在cmp_to_key
函数,可以将cmp
函数转换为key
函数。我的问题是我们是否可以将其编写为键函数而不必那样转换。
由于您已经排除了像functools.cmp_to_key
那样工作的解决方案(即使用dunder比较方法声明一个类),因此我推断出您想要一种在键函数仅使用内置类型的情况下执行此操作的方法。
问题是,从逻辑上讲,像25这样的数字的关键是无限序列(2, 5, 2, 5, ...)
。您需要无限序列的原因是,您总是会遇到像252525252525253这样的数字,其中比较的结果取决于最后一个数字,因为其余数字是从另一个数字开始的重复序列。
如果您对输入数字的大小有限制(例如,我们知道它们最多为10位数字),则只需重复该序列,直到10位数字的长度,然后进行字典比较(例如字符串)或元组)将起作用:
def key_func(n, digits=10):
s = str(n)
return (s * digits)[:digits]
但是,正如Stefan Pochmann指出的那样,有一个内置类型Fraction
,可用于表示数字的无限重复序列:例如,Fraction
表示为(2, 5, 2, 5, ...)
,因为其十进制扩展为Fraction(25, 99)
。比较分数等于按字典顺序比较其十进制扩展:
0.2525...
示例(两个关键功能相同):
from fractions import Fraction
def key_func(n):
k = len(str(n))
return Fraction(n, 10**k - 1)
结果列表应以相反的顺序连接,以通过串联产生尽可能多的数字,例如>>> sorted([54, 546, 548, 60], key=key_func)
[54, 546, 548, 60]
>>> sorted([1, 34, 3, 98, 9, 76, 45, 4], key=key_func)
[1, 3, 34, 4, 45, 76, 98, 9]
>>> sorted([25, 252525251], key=key_func)
[252525251, 25]
>>> sorted([25, 252525253], key=key_func)
[25, 252525253]
映射到[54, 546, 548, 60]
。
此比较器只是反转两个字符串之间的字符串比较的一种round回方式:
6054854654
通过字符串排序的方式执行相同的操作。如果a和b是字符串,则a