Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sorting in lexicographical order

Tags:

sorting

ruby

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 }
like image 216
Jake Senior Avatar asked Feb 17 '15 08:02

Jake Senior


People also ask

What is lexicographic order example?

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.

How do you sort letters in 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).

How do I arrange string in lexicographically?

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.

What is lexicographical order in coding?

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.


2 Answers

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.

like image 167
Frederick Cheung Avatar answered Sep 18 '22 04:09

Frederick Cheung


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 method between?.

like image 33
Stefan Avatar answered Sep 19 '22 04:09

Stefan