Ruby Array#sort_by
Let's say we have the following list of very interesting items.
items = [
{ name: "dogfood", price: 4.99 },
{ name: "catfood", price: 5.99 },
{ name: "batfood", price: 4.99 }
]
Our client wants the list sorted by price descending, and we should break ties in price by then sorting by item name descending. So with our example list, the result should be:
items = [
{ name: "batfood", price: 4.99 },
{ name: "dogfood", price: 4.99 },
{ name: "catfood", price: 5.99 }
]
Here's a method that does the job for our client:
def sort_by_price_and_name(items)
items
.group_by { |i| i[:price] }
.map { |_k,v| v.sort { |a, b| a[:name] <=> b[:name] } }
.flatten
end
It's a bit unwieldy and inelegant. It turns out there is a perfect method for this in Ruby:
def sort_by_price_and_name(items)
items.sort_by { |i| [i[:price], i[:name]] }
end
Ruby's Enumerable#sort_by
works in this case where we sort by all the fields in ascending order. If we wanted to sort by price ascending, then name descending, sort_by
would no longer be the tool we'd want to use.
Hat tip to @joshcheek for the knowledge.
Tweet