Sort Array of Arrays by length with tiebreaker

You can still do this with sort_by, you just need to realize that Ruby arrays compare element-by-element:

ary <=> other_ary → -1, 0, +1 or nil

[...]

Each object in each array is compared (using the <=> operator).

Arrays are compared in an “element-wise” manner; the first two elements that are not equal will determine the return value for the whole comparison.

That means that you can use arrays as the sort_by key, then throw in a bit of integer negation to reverse the sort order and you get:

a.sort_by { |e| [-e.length, -e.last] }

That will give you the [[4, 5, 6, 7], [1, 2, 9], [1, 2, 3]] that you're looking for.

If you're not using numbers so the "negation to reverse the order" trick won't work, then use Shaunak's sort approach.


There you go :

a =  [ [1, 2, 9],[4, 5, 6, 7],[1, 2, 3] ]
a.sort { |a, b| (b.count <=> a.count) == 0 ? (b.last <=> a.last): (b.count <=> a.count)  } 

That should give you:

[[4, 5, 6, 7], [1, 2, 9], [1, 2, 3]]

How this works: we pass a block to sort function, which first checks if the array length is same, if not it continues to check for last element.


You could use

a.sort_by {|i| [i.length, i.last] }.reverse
# => [[4, 5, 6, 7], [1, 2, 9], [1, 2, 3]]