嗨,我正在 leetcode 上解决这个问题 [给定一个非负整数列表,将它们排列成最大的数字。] 我看到了这个解决方案。我无法理解 LargerNumKey 类是如何工作的?另外,lt的目的是什么?什么是变量 x 和 y
class LargerNumKey(str):
def __lt__(x, y):
return x+y > y+x
class Solution:
def largestNumber(self, nums):
largest_num = ''.join(sorted(map(str, nums), key=LargerNumKey))
return '0' if largest_num[0] == '0' else largest_num
Run Code Online (Sandbox Code Playgroud)
在__lt__“dunder”的方法是什么让您使用<小于符号的对象。写成如下可能更有意义:
class LargerNumKey(str):
def __lt__(self, other):
return self+other > other+self
# This calls into LargerNumKey.__lt__(LargerNumKey('0'), LargerNumKey('1'))
LargerNumKey('0') < LargerNumKey('1')
Run Code Online (Sandbox Code Playgroud)
在str子类化时的幕后,添加self+other实际上生成一个str对象而不是一个LargerNumKey对象,因此您不会遇到无限递归问题,根据其自己的不等运算符定义类型上的不等式。
这样做的原因可能更有趣:
(x>y) == (str(x)>str(y)),因此当自定义__lt__操作时,它实际上是在询问由这些字符串连接表示的整数是大于还是小于彼此。s<t和t<uthen s<u,因此该sorted()方法能够通过获得每个可能对的正确答案来将所有数字按正确顺序排列。__lt__是一个神奇的方法,可以让你改变操作员的行为<。sorted使用<运算符来比较值。因此,当 python 比较两个值时,<它会检查这些对象是否__lt__定义了魔术方法。如果存在,则使用该方法进行比较。示例中的变量x和是要比较的两个变量。y因此,如果您有一行类似 的代码x < y,那么x和y将作为参数传递给__lt__。Sorted 大概有那行代码。但您不必将它们称为“x”和“y”,您可以随意称呼它们。通常您会看到它们被称为self和other。
sorted通过一次比较两个项目来工作。例如,我们称它们x为 和y。因此sorted必须在某个地方比较它们,可能使用如下所示的行:
if x < y:
Run Code Online (Sandbox Code Playgroud)
但是,如果您传递sorted一个key参数,那么它会像这样比较它们:
if key(x) < key(y):
Run Code Online (Sandbox Code Playgroud)
由于该示例LargerNumKey作为传递key,因此在 python 查找后它最终看起来像这样key:
if LargerNumKey(x) < LargerNumKey(y):
Run Code Online (Sandbox Code Playgroud)
当 python 看到该<运算符时,它会查找该__lt__方法,并且因为找到了该方法,所以它基本上将该语句变成:
if LargerNumKey(x).__lt__(LargerNumKey(y)):
Run Code Online (Sandbox Code Playgroud)
因为__lt__是对象上的方法,所以对象本身成为第一个参数(x在本例中)。另外,因为LargerNumKey是 的子类,所以它的str行为与常规字符串完全相同,除了__lt__您覆盖的方法。
当您希望事物可排序时,这是一种有用的技术。您可以使用它__lt__来允许以您希望的任何方式对对象进行排序。如果您要排序的对象__lt__定义了方法,那么您甚至不必传递key. 但由于我们正在处理不同类型的对象并且不想使用默认__lt__方法,key因此我们使用。
参考:
请注意,虽然我的示例假装sorted是 python 代码,但实际上通常是c 代码。然而,由于python是“运行的伪代码”,我认为它准确地传达了这个想法。
| 归档时间: |
|
| 查看次数: |
1569 次 |
| 最近记录: |