红宝石的< =>运算符和排序方法 [英] ruby's <=> operator and sort method

查看:98
本文介绍了红宝石的< =>运算符和排序方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

player1 = Player.new("moe")
player2 = Player.new("larry",60)
player3 = Player.new("curly", 125)
@players = [player1, player2, player3]

上面,我创建了一些播放器对象,并将它们添加到以前为空的数组@players中.

Above, I created some player objects and added them to the previously empty array @players.

然后,我将< =>重新定义为:

Then, I redefined <=> to be this:

def <=>(other)
    other.score <=> score
end 

然后我可以运行这段代码

I then can run this code

@players.sort

,我在@players中的玩家对象数组从高分到低分排序. 我想这对我来说有点黑框.我不太清楚这是怎么回事.我如何找出幕后发生的事情?

and my array of player objects in @players are sorted from high score to low score. I guess this looks a bit black boxy to me. I am a bit unclear what's going on here. How do I find out what is going on behind the scenes?

我所知道的是,如果您采用两个值并使用太空飞船运算符/一般比较运算符:

All I know is that if you take two values and use the spaceship operator/general comparison operator:

2 <=> 1   
=> 1

1 <=> 2
=> -1

1 <=> 1
=>0

有时候,似乎Ruby有很多底层的东西,在我正在编程的高层上我看不到.这似乎很自然...但是这种情况似乎特别从底层去除了.进行排序的方法.排序如何使用飞船运算符?为什么以我们现在允许对物体进行排序的方式重新定义太空飞船操作员?

Sometimes, it seems like Ruby has a lot of lower level stuff going on that I can't see at the high level that I am programming in. This seems natural... but this case seems especially removed from the lower level goings on of the sort method. How does sort use the spaceship operator? Why does redefining the spaceship operator in the way that we did allow us to sort objects now?

推荐答案

在您了解排序对象之前.您需要了解Ruby中的.sort方法.如果您要排序5张带有数字的卡片,则可以查看所有卡片,轻松找到最低的卡片,然后选择那张卡片作为第一张卡片(假设您是按照从最低到最高的顺序排序,这是Ruby做).当您的大脑进行排序时,它可以查看所有内容并从那里进行排序.

Before you can understand sorting objects. You need to understand the .sort method in Ruby. If you were to sort 5 cards with numbers on them, you could take a look at all of them, find the lowest one easily, and just pick that one as your first card (presuming you're sorting from lowest to highest, which Ruby does). When your brain sorts, it can look at everything and sort from there.

这里有2个主要的混乱要素,很少解决:

There are 2 main elements of confusion here that are rarely addressed:

1)Ruby无法按照您认为"sort"的方式进行排序. Ruby只能交换"数组元素,并且可以比较"数组​​元素.

1) Ruby can't sort in the way you think of the word "sort". Ruby can only 'swap' array elements, and it can 'compare' array elements.

2)Ruby使用比较运算符(称为太空飞船)来赋予数字属性以帮助其排序".这些数字是-1,0,1.人们错误地认为这3个数字正在帮助它排序"(例如,如果有一个包含3个数字的数组,例如10、20、30,则10将是-1,20将是0,而30将是1 ,而Ruby只是通过将其减少到-1,0,1来简化排序.这是错误的.Ruby不能排序".它不能只进行比较).

2) Ruby uses a comparison operator, called the spaceship, to attribute numbers to help it 'sort'. Those numbers are -1,0,1. People erroneously think those 3 numbers are helping it 'sort' (eg. if there was an array with 3 numbers such a 10,20,30, then the 10 would be a -1, the 20 a 0, and the 30 a 1, and Ruby is just simplifying the sorting by reducing it to -1,0,1. This is wrong. Ruby can't "sort". It can't only compare).

看一下太空飞船的操作员.它是3个单独的运算符,分别是<,=和>. Ruby比较两个变量时,将得出其中一个数字.

Look at the spaceship operator. It's 3 individual operators lumped into one, the <, the =, and the >. When Ruby compares two variables, it results in one of these numbers.

也就是说,结果"是什么意思?这并不意味着为变量之一分配了0,1,-1.这只是Ruby可以采用两个变量并对它们执行某些操作的一种方式.现在,如果您只是运行:

That said, what does "results" mean? It DOESN'T mean that one of the variables is assigned a 0,1,-1. It simply is a way what Ruby can take two variables and do something with them. Now, if you just run:

puts 4 <=> 5

您将得到-1的结果,因为比较运算符(太空飞船)的任何部分"(例如<,=或>)都为true,则得到分配给它的数字(如以上图片).当Ruby看到带有数组的< =>时,它只对数组有两件事:保留数组或交换数组的元素.

You'll get the result of -1, since whatever 'part' (eg. <, =, or >) of the comparison operator (spaceship) is true, gets the number that's assigned to it (as seen in the above picture). When Ruby sees this <=> with an array though, it has 2 things it will do to the array only: Leave the array alone OR swap the elements of the array.

如果Ruby使用< =>并得到1,它将交换数组的2个元素.如果Ruby得到-1或0的结果,它将不理会该数组.

If Ruby uses the <=> and gets a 1, it will swap the 2 elements of the array. If Ruby gets a result of -1 or 0, it will leave the array alone.

一个示例是Ruby是否看到数组[2,1].排序方法将使其拉入这些数字,如2 = 1.由于飞船的一部分(如果您想这样想)是>(即2> 1是true),因此从Ruby得到的结果是"1".当Ruby看到飞船的结果为1时,它会交换该数组的2个元素.现在数组是[1,2].

An example is if Ruby sees the array [2,1]. The sort method would make it pull in these figures like 2<=>1. Since the part of the spaceship (if you want to think of it like that) that's true is the > (ie. 2>1 is true), the result is '1' from Ruby. When Ruby sees a 1 result from the spaceship, it swaps the 2 elements of the array. Now the array is [1,2].

希望在这一点上,您将看到Ruby仅与< =>运算符进行比较,然后交换(或单独留下)它比较的数组中的2个元素.

Hopefully at this point, you see that Ruby only compares with the <=> operator, and then swaps (or leaves alone) the 2 elements in the array it compares.

了解.sort方法是一种迭代方法,这意味着它是多次运行代码块的方法.大多数人只有在看到诸如.each或.upto之类的方法(如果您从未听说过它们的话,便无需知道它们的作用)后,才被介绍给.sort方法.阵列仅1次. .sort方法的不同之处在于,它将按需要多次遍历数组,以便对其进行排序(通过排序,我们指的是比较和交换).

Understand the .sort method is an iterative method, meaning that it's a method that runs a block of code many times. Most people are introduced to the .sort method only after they've seen a methods such as .each or .upto (you don't need to know what those do if you haven't heard of them), but those methods run through the array 1 time ONLY. The .sort method is different in that it will run through your array as many times as it needs to so that it's sorted (by sorted, we mean compared and swapped).

为确保您了解Ruby语法,

To make sure you understand the Ruby syntax:

foo = [4, 5, 6]
puts foo.sort {|a,b| a <=> b}

代码块(由{}包围)是Ruby从最低到最高排序时会采取的任何方式.但是只要说.sort方法的第一次迭代就可以在管道的前两个元素(a,b)之间分配变量.因此对于第一次迭代,a = 4并且b = 5,并且由于4 <5,所以导致-1,Ruby认为它意味着不交换阵列.它对第二次迭代执行此操作,这意味着a = 5和b = 6,看到5 <6,结果为-1,并且不理会数组.由于所有< =>结果均为-1,因此Ruby停止循环遍历,并感觉数组在[4,5,6]处进行了排序.

The block of code (surrounded by {}'s) is what Ruby would do any way when it sorts from lowest to highest. But suffice it to say that the first iteration of the .sort method will assign the variables between the pipes (a, b) the first two elements of the array. So for the first iteration a=4 and b=5, and since 4<5, that results in a -1, which Ruby takes it to mean to NOT swap the array. It does this for a second iteration, meaning a=5 and b=6, sees that 5<6, results in -1 and leaves the array alone. Since all the <=> results were -1, Ruby stops looping through and feels the array is sorted at [4,5,6].

我们可以通过简单地交换变量的顺序来从高到低排序.

We can sort from high to low by simply swapping the order of the variables.

bar = [5, 1, 9]
puts bar.sort {|a,b| b <=> a}   

这是Ruby在做什么:

Here's what Ruby is doing:

迭代1:数组[ 5,1 ,9]. a = 5,b = 1. Ruby看到b< => a,说是1< 5?是的.结果为-1.保持原样.

Iteration 1: Array [5,1,9]. a=5, b=1. Ruby sees the b<=>a, and says is 1 < 5? Yes. That results in -1. Stay the same.

迭代2:数组[5, 1,9 ]. a = 1,b = 9. Ruby看到b< => a,并说是9< 1个?否.结果为1.交换2个数组元素.数组现在为[5,9,1]

Iteration 2: Array [5,1,9]. a=1, b=9. Ruby sees the b<=>a, and says is 9 < 1? No. That results in 1. Swap the 2 array elements. The array is now [5,9,1]

迭代3:数组[ 5,9 ,1].从b/c开始,在遍历所有数组之前,数组中的结果为+1. a = 5,b = 9. Ruby看到b< => a,说是9< 5?否.结果为1.交换. [9,5,1]

Iteration 3: Array [5,9,1]. Starting over b/c there was a +1 result in the array before going through it all. a=5, b=9. Ruby sees the b<=>a, says is 9<5? No. That results in 1. Swap. [9, 5, 1]

迭代4:数组[9, 5,1 ]". a = 5,b = 1. Ruby看到b< => a,说是1< 5?是的.结果为-1.因此,不执行任何交换.完毕. [9,5,1].

Iteration 4: Array [9,5,1]. a=5, b=1. Ruby sees the b<=>a, says is 1<5? Yes. That results in -1. Therefore, no swapping is performed. Done. [9,5,1].

想象一下一个数组,其中前999个元素的数字为50,而元素1000的数字为1.如果您意识到Ruby必须经过数千次相同的简单比较和交换遍历该数组,则可以充分理解sort方法.例程,将 1 一直移动到数组的开头.

Imagine an array with the number 50 for the first 999 elements, and a 1 for element 1000. You fully understand the sort method if you realize Ruby has got to go through this array thousands of times doing the same simple compare and swap routine to shift that 1 all the way to the beginning of the array.

现在,当涉及到对象时,我们终于可以看一下.sort了.

Now, we can finally look at .sort when comes to an object.

def <=>(other)
    other.score <=> score
end 

这现在应该更有意义了.在对象上调用.sort方法时,例如运行

This should now make a little more sense. When the .sort method is called on an object, like when you ran the:

@players.sort

它使用参数(例如其他")从@players中获取具有当前对象的参数(例如无论当前实例对象是'@players'的任何对象)"的"def< =>"方法这是sort方法,最终将遍历'@players'数组的所有元素).就像您尝试在类上运行puts方法时,它会自动在该类内调用to_s方法.自动查找< =>方法的.sort方法也是如此.

it pulls up the "def <=>" method with the parameter (eg. 'other') which has the current object from @players (eg. 'whatever the current instance object is of '@players', since it's the sort method, it's eventually going to go through all of the elements of the '@players' array). It's just like when you try to run the puts method on a class, it automatically calls the to_s method inside that class. Same thing for the .sort method automatically looking for the <=> method.

查看< =>方法内部的代码,该类中必须有一个.score实例变量(带有访问器方法)或只是一个.score方法. .score方法的结果应该(希望)是一个字符串或数字-ruby可以排序"的两件事.如果是数字,则Ruby使用它的< =>'sort'操作来重新排列所有这些对象,因为它知道这些对象的哪一部分要排序(在这种情况下,这是.score方法或实例的结果)多变的).

Looking at the code inside of the <=> method, there must be a .score instance variable (with an accessor method) or simply a .score method in that class. And the result of that .score method should (hopefully) be a String or number - the 2 things ruby can 'sort'. If it's a number, then Ruby uses it's <=> 'sort' operation to rearrange all of those objects, now that it knows what part of those objects to sort (in this case, it's the result of the .score method or instance variable).

作为最后一个花絮,Ruby也通过将其转换为数字值来按字母顺序进行排序.它只是考虑为任何字母分配ASCII代码(这意味着,由于大写字母在ASCII码表上的数值较小,因此默认情况下大写字母将排在首位).

As a final tidbit, Ruby sorts alphabetically by converting it to numerical values as well. It just considers any letter to be assigned the code from ASCII (meaning since upper case letters have lower numerical values on the ASCII code chart, upper case will be sorted by default to be first).

希望这会有所帮助!

这篇关于红宝石的&lt; =&gt;运算符和排序方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆