So I want to sort my array of coordinates in lexicographical order. But I'm not sure how to do that. Each element in the array is a Coordinate
object, with Fixnum
fields #x
and #y
.
I'm new to Ruby and don't necessarily understand the sort enumeration. Would it be something like this?
coordinate_array.sort! { |a,b| a.x <==> b.x && a.y <==> b.y }
Lexicographical order is nothing but the dictionary order or preferably the order in which words appear in the dictonary. For example, let's take three strings, "short", "shorthand" and "small". In the dictionary, "short" comes before "shorthand" and "shorthand" comes before "small". This is lexicographical order.
Sorting words in lexicographical order mean that we want to arrange them first by the first letter of the word. Then for the words whose first letter is the same, we arrange them within that group by the second letter and so on just like in a language's dictionary(not the data structure).
Approach: The idea is to sort the given array of strings using the inbuilt sort function using the below comparator function. The comparator function used to check if any string occurs as a substring in another string using compare() function in C++ then, it should arrange them in decreasing order of their length.
Thus, lexicographical order is a way for formalizing word order where the order of the underlying symbols is given. In programming, lexicographical order is popularly known as Dictionary order and is used to sort a string array, compare two strings, or sorting array elements.
First the spaceship operator is <=>
not <==>
Secondly you're not combining the 2 comparisons correctly: the result of the comparison will be -1,0,or 1. These are all truthy values and true && foo
is just foo
, so your code would just sort by the y values
You could write this as
x_ordering = a.x <=> b.x
x_ordering == 0 ? a.y <=> b.y : x_ordering
However array already implements <=>
so you could just do
array.sort! { |a,b| [a.x, a.y] <=> [b.x, b.y]}
Which is a little terser and clearer at expense of creating 2 arrays in each comparison
You could even do
array.sort_by! { |a| [a.x, a.y] }
Which is even clearer, but with a slightly different memory profile. This creates an array with the original values replaced by the values returned by the block and uses that to sort the original array.
I'd usually use the latter version unless I had a compelling reason to do otherwise.
Frederick Cheung's answer already describes how to sort by custom attributes.
Another option is to provide a default sort order by implementing Coordinate#<=>
:
class Coordinate
# ...
def to_a
[x, y]
end
def <=>(other)
return unless other.is_a? Coordinate
to_a <=> other.to_a
end
end
And just call:
coordinate_array.sort!
You can also include the Comparable
mixin which ...
(...) uses
<=>
to implement the conventional comparison operators (<
,<=
,==
,>=
, and>
) and the methodbetween?
.
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