Sorting: Sort array based on multiple conditions in Ruby
This should do the trick:
array.sort { |a,b| [ a[1], a[0] ] <=> [ b[1], b[0] ] }
So what does this do? It uses a lot of Ruby idioms.
- First is blocks, which are sort of like callbacks or anonymous functions/classes in other languages. The
sort
method of Array uses them to compare two elements based on the return value of the block. You can read all about them here. - Next is the
<=>
operator. It returns -1 if the first argument is less than the second, 0 if they are equal, and 1 if the first is greater than the second. When you use it with arrays, it will compare the arrays element-wise until one of them returns -1 or 1. If the arrays are equal, you will get 0.
You should always use sort_by
for a keyed sort. Not only is it much more readable, it is also much more efficient. In addition, I would also prefer to use destructuring bind, again, for readability:
array.sort_by {|name, age| [age, name] }
As I understand it you want to order by age first, and then if more than one record has the same age, arrange that subset by name.
This works for me
people = [
["bob", 15, "male"],
["alice", 25, "female"],
["bob", 56, "male"],
["dave", 45, "male"],
["alice", 56, "female"],
["adam", 15, "male"]
]
people.sort{|a,b| (a[1] <=> b[1]) == 0 ? (a[0] <=> b[0]) : (a[1] <=> b[1]) }
# The sorted array is
[["adam", 15, "male"],
["bob", 15, "male"],
["alice", 25, "female"],
["dave", 45, "male"],
["alice", 56, "female"],
["bob", 56, "male"]]
What this is doing is comparing by age first, and if the age is the same (<=> returs 0) it comparing the name.