I am having a problem understanding how array.sort{ |x,y| block }
works exactly, hence how to use it?
An example from Ruby documentation:
a = [ "d", "a", "e", "c", "b" ] a.sort #=> ["a", "b", "c", "d", "e"] a.sort { |x,y| y <=> x } #=> ["e", "d", "c", "b", "a"]
Arrays are extremely powerful data structures that store elements of the same type. The type of elements and the size of the array are fixed and defined when you create it. Memory is allocated immediately after the array is created and it's empty until you assign the values.
An array is a collection of similar types of data. For example, if we want to store the names of 100 people then we can create an array of the string type that can store 100 names. String[] array = new String[100];
An array is a series of memory locations – or 'boxes' – each of which holds a single item of data, but with each box sharing the same name. All data in an array must be of the same data type . This would work, but there is a better way. It is much simpler to keep all the related data under one name.
Obtaining an array is a two-step process. First, you must declare a variable of the desired array type. Second, you must allocate the memory to hold the array, using new, and assign it to the array variable. Thus, in Java, all arrays are dynamically allocated.
In your example
a.sort
is equivalent to
a.sort { |x, y| x <=> y }
As you know, to sort an array, you need to be able to compare its elements (if you doubt that, just try to implement any sort algorithm without using any comparison, no <
, >
, <=
or >=
).
The block you provide is really a function which will be called by the sort
algorithm to compare two items. That is x
and y
will always be some elements of the input array chosen by the sort
algorithm during its execution.
The sort
algorithm will assume that this comparison function/block will meet the requirements for method <=>
:
Failure to provide an adequate comparison function/block will result in array whose order is undefined.
You should now understand why
a.sort { |x, y| x <=> y }
and
a.sort { |x, y| y <=> x }
return the same array in opposite orders.
To elaborate on what Tate Johnson added, if you implement the comparison function <=>
on any of your classes, you gain the following
Comparable
in your class which will automatically define for you the following methods: between?
, ==
, >=
, <
, <=
and >
.sort
.Note that the <=>
method is already provided wherever it makes sense in ruby's standard library (Bignum
, Array
, File::Stat
, Fixnum
, String
, Time
, etc...).
When you have an array of, let's say, integers to sort, it's pretty straightforward for sort
method to order the elements properly - smaller numbers first, bigger at the end. That's when you use ordinary sort
, with no block.
But when you are sorting other objects, it may be needed to provide a way to compare (each) two of them. Let's say you have an array of objects of class Person
. You probably can't tell if object bob
is greater than object mike
(i.e. class Person
doesn't have method <=>
implemented). In that case you'd need to provide some code to explain in which order you want these objects sorted to sort
method. That's where the block form kicks in.
people.sort{|p1,p2| p1.age <=> p2.age} people.sort{|p1,p2| p1.children.count <=> p2.children.count}
etc. In all these cases, sort
method sorts them the same way - the same algorithm is used. What is different is comparison logic.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With