在您能够理解对象排序之前。您需要了解 Ruby 中的 .sort 方法。如果您要对 5 张带有数字的卡片进行排序,您可以查看所有卡片,轻松找到最低的一张,然后选择那一张作为您的第一张卡片(假设您从最低到最高排序,Ruby做)。当你的大脑进行排序时,它可以查看所有内容并从那里进行排序。
这里有两个主要的混淆因素很少被解决:
1) Ruby 无法按照您想象的“排序”一词的方式进行排序。 Ruby 只能“交换”数组元素,也可以“比较”数组元素。
2) Ruby 使用称为 spaceship 的比较运算符来对数字进行属性以帮助其“排序”。这些数字是-1,0,1。人们错误地认为这 3 个数字正在帮助它“排序”(例如,如果有一个包含 3 个数字的数组,例如 10、20、30,那么 10 将是 -1,20 将是 0,30 将是 1 ,而 Ruby 只是通过将其减少为 -1,0,1 来简化排序。这是错误的。Ruby 不能“排序”。它不能只进行比较)。
看看宇宙飞船的操作员。它由 3 个单独的运算符合为一个:。当 Ruby 比较两个变量时,它会得出这些数字之一。
那么,“结果”是什么意思呢?这并不意味着其中一个变量被分配了 0,1,-1。这只是 Ruby 获取两个变量并用它们做某事的一种方式。现在,如果你运行:
puts 4 <=> 5
您将得到 -1 的结果,因为比较运算符(宇宙飞船)的任何“部分”(例如 )为 true,都会获取分配给它的数字(如上图所示) 。当 Ruby 看到这个 与数组时,它只会对数组做两件事:保留数组或交换数组的元素。
如果 Ruby 使用 并得到 1,它将交换数组的 2 个元素。如果 Ruby 得到的结果是 -1 或 0,它将不处理该数组。
一个例子是 Ruby 看到数组 [2,1]。 sort 方法将使其提取这些数字,如 21。由于宇宙飞船的部分(如果你想这样想的话)为真的是 > (即 2>1 为真),所以 Ruby 的结果是“1”。当 Ruby 从宇宙飞船中看到 1 结果时,它swaps数组的 2 个元素。现在数组是[1,2]。
希望此时您会看到 Ruby 仅与 运算符进行比较,然后交换(或保留)它比较的数组中的 2 个元素。
了解 .sort 方法是一种迭代方法,这意味着它是一种多次运行代码块的方法。大多数人只是在看到 .each 或 .upto 等方法之后才会了解 .sort 方法(如果您没有听说过它们,则无需知道它们的作用),但这些方法贯穿始终仅阵列 1 次。 .sort 方法的不同之处在于,它将根据需要多次运行数组,以便对其进行排序(通过排序,我们的意思是比较和交换)。
为了确保您理解 Ruby 语法:
foo = [4, 5, 6]
puts foo.sort {|a,b| a <=> b}
代码块(由 {} 包围)是 Ruby 从最低到最高排序时会执行的操作。但只要说 .sort 方法的第一次迭代将在管道 (a, b) 之间分配数组的前两个元素的变量就足够了。因此,对于第一次迭代 a=4 和 b=5,并且由于 4 结果均为 -1,Ruby 停止循环并感觉数组已按 [4,5,6] 排序。
我们可以通过简单地交换变量的顺序来从高到低排序。
bar = [5, 1, 9]
puts bar.sort {|a,b| b <=> a}
这是 Ruby 正在做的事情:
迭代 1:数组 [5,1,9]。 a=5,b=1。 Ruby 看到 ba,并说 1
迭代 2:数组 [5,1,9]。 a=1,b=9。 Ruby 看到 ba,并说 9
迭代 3:数组 [5,9,1]。从 b/c 开始,在遍历所有内容之前,数组中有 +1 结果。 a=5,b=9。 Ruby 看到 ba,说是 9
迭代 4:数组 [9,5,1]。 a=5,b=1。 Ruby 看到 ba,说是 1
想象一个数组,前 999 个元素的编号为 50,第 1000 个元素的编号为 1。如果您意识到 Ruby 必须遍历该数组数千次,执行相同的简单比较和交换例程才能进行移位,那么您就完全理解了排序方法那1一直到数组的开头。
现在,我们终于可以看看对象的 .sort 了。
def <=>(other)
other.score <=> score
end
现在这应该更有意义了。当对对象调用 .sort 方法时,例如运行以下命令时:
@players.sort
它使用参数(例如“other”)提取“def ”方法,该参数具有来自@players的当前对象(例如“无论当前实例对象是什么”@players',因为它是排序方法,它最终会遍历“@players”数组的所有元素)。就像当您尝试在类上运行 put 方法时,它会自动调用该类内的 to_s 方法。 .sort 方法自动查找 方法也是如此。
查看 方法内部的代码,该类中必须有一个 .score 实例变量(带有访问器方法)或只是一个 .score 方法。 .score 方法的结果应该(希望)是一个字符串或数字——这是 ruby 可以“排序”的两件事。如果它是一个数字,那么 Ruby 使用它的 'sort' 操作来重新排列所有这些对象,现在它知道要对这些对象的哪一部分进行排序(在本例中,它是 .score 方法或实例变量的结果) )。
最后一点,Ruby 还通过将其转换为数值来按字母顺序排序。它只考虑为任何字母分配 ASCII 代码(这意味着由于大写字母在 ASCII 代码表上的数值较低,因此默认情况下大写字母会排在第一位)。
希望这可以帮助!