Marrento
Marrento

Reputation: 329

How to find the max value in an array of hashes?

Given this array of hashes here:

arr = [{:question_type=>"Fire", :total=>0.0}, {:question_type=>"Water", :total=>0.0}, {:question_type=>"Metal", :total=>0.0}, {:question_type=>"Earth", :total=>0.0}, {:question_type=>"Wood", :total=>100.0}]

I would like to pick the hash with the highest value for the total key. So the code bellow seems to do the work

max = arr.max_by{|x| x[:total]}
puts max[:question_type]
#=> Wood

However if I have 2 hashes with the same value it will return the first one only

arr2 = [{:question_type=>"Fire", :total=>0.0}, {:question_type=>"Water", :total=>0.0}, {:question_type=>"Metal", :total=>0.0}, {:question_type=>"Earth", :total=>50.0}, {:question_type=>"Wood", :total=>50.0}]

max = arr2.max_by{|x| x[:total]} #it should be arr2
puts max[:question_type]
#=> Earth

What would be the best way to get it to return Earth and Wood in case both are the highest values?

Upvotes: 1

Views: 2231

Answers (4)

Zoran
Zoran

Reputation: 4226

An alternative approach to some solid answers already posted here is to roll your own method to retrieve the max values, including multiples if there are ties:

def get_max(arr)
  result = []
  current_max = 0.0
  arr.each do |hash|
    if hash[:total] > current_max
      result = [hash[:question_type]]
      current_max = hash[:total]
    elsif hash[:total] == current_max
      result.push(hash[:question_type])
    end
  end
  result
end


arr = [{:question_type=>"Fire", :total=>0.0}, {:question_type=>"Water", :total=>0.0}, {:question_type=>"Metal", :total=>0.0}, {:question_type=>"Earth", :total=>50.0}, {:question_type=>"Wood", :total=>50.0}]
puts get_max(arr)
# => ["Earth", "Wood"]

It may not be as succinct as using something like #max_by and #select, but the benefit of the above approach is you only iterate through the array once.

Hope it helps!

Upvotes: 0

potashin
potashin

Reputation: 44581

You can do this with group_by and max:

arr.group_by { |x| x[:total] }.max.last

Upvotes: 6

Tom Aranda
Tom Aranda

Reputation: 6026

You could do this in tow steps this way:

max = arr.max_by{|x| x[:total]}
max = arr.select{ |x| x[:total] == max[:total }

Upvotes: 1

Andrew
Andrew

Reputation: 7545

You can always just take that max value and select.

arr = [{:question_type=>"Fire", :total=>0.0}, {:question_type=>"Water", :total=>0.0}, {:question_type=>"Metal", :total=>0.0}, {:question_type=>"Earth", :total=>50.0}, {:question_type=>"Wood", :total=>50.0}]

max = arr.max_by{|x| x[:total]}
max_values = arr.select{|hash| hash[:total] == max[:total]}

Upvotes: 0

Related Questions