itsh
itsh

Reputation: 1123

How to sort an array of hashes with multiple values?

I have an array of hashes which contains an id field and a weight field. I am able to sort it based on weight but I also need to make sure that the id field is sorted if there are duplicate weights. Below is the code snippet for reference.

# Input
arr = [{"id" => 10, "weight" => 23}, {"id" => 6, "weight" => 43}, {"id" => 12, "weight" => 5}, {"id" => 15, "weight" => 30}, {"id" => 11, "weight" => 5}]

arr.sort_by{|k| k["weight"]}

# Output: [{"id"=>12, "weight"=>5}, {"id"=>11, "weight"=>5}, {"id"=>10, "weight"=>23}, {"id"=>15, "weight"=>30}, {"id"=>6, "weight"=>43}]

# Expected output = [{"id"=>11, "weight"=>5}, {"id"=>12, "weight"=>5}, {"id"=>10, "weight"=>23}, {"id"=>15, "weight"=>30}, {"id"=>6, "weight"=>43}]

In the above example, id = 12 and id = 11 have the duplicate values. I need to have id = 11 before id = 12 in the array. I really appreciate some guidance on this. Thank you!

Upvotes: 1

Views: 552

Answers (2)

spickermann
spickermann

Reputation: 106802

You can use Enumerable#sort_by with an array too. Note the order of the values in the array.

arr.sort_by {|k| k.values_at("weight", "id") }

Quote from the docs of Array#<=> about how comparison of array works:

Arrays are compared in an “element-wise” manner; the first element of ary is compared with the first one of other_ary using the <=> operator, then each of the second elements, etc… As soon as the result of any such comparison is non zero (i.e. the two corresponding elements are not equal), that result is returned for the whole array comparison.

Upvotes: 4

max pleaner
max pleaner

Reputation: 26758

You can use Array#sort with the spaceship operator like so:

arr.sort do |a,b|
  if a["weight"] == b["weight"]
    a["id"] <=> b["id"]
  else
    a["weight"] <=> b["weight"]
  end
end

Upvotes: 1

Related Questions