127

I have the following hash {"CA"=>2, "MI"=>1, "NY"=>1}

How can I return the maximum key value pair using ruby? I would like it to return "CA"

JZ.
  • 21,147
  • 32
  • 115
  • 192

8 Answers8

262

This will return max hash key-value pair depending on the value of hash elements:

def largest_hash_key(hash)
  hash.max_by{|k,v| v}
end
Hck
  • 9,087
  • 2
  • 30
  • 25
49

I found this way , return the key of the first max value

hash.key(hash.values.max)
Paul Pettengill
  • 4,843
  • 1
  • 29
  • 33
  • 2
    While `hash[key]` is very efficient, `hash.key(value)` has to search the whole hash. This answer searches the hash twice: first to find the maximum value, then to find the key which matches that value. – Schwern Jan 20 '22 at 00:16
15

Another way could be as follows:

hash.each { |k, v| puts k if v == hash.values.max }

This runs through each key-value pair and returns (or in this case puts's) the key(s) where the value is equal to the max of all values. This should return more than one key if there's a tie.

Pang
  • 9,564
  • 146
  • 81
  • 122
5

If you want to retrieve more than one key value pair based on order(second largest, smallest etc.), a more efficient way will be to sort the hash once and then get the desired results.

def descend_sort(hash)
   hash = hash.sort_by {|k,v| v}.reverse
end

Key of largest value

puts *hash[0][0]

Get max and min

puts *hash[0], *hash[hash.length-1]

2nd largest key value pair

Hash[*hash[1]]

To convert the hash array back into a hash

hash.to_h
Linju
  • 335
  • 3
  • 9
4

You can use the select method if you want the key value pair returned:

hash.select {|k,v| v == hash.values.max }
ecoding5
  • 404
  • 6
  • 19
4

I did this today on a similar problem and ended up with this:

hash = { "CA"=>2, "MI"=>1, "NY"=>1 }

hash.invert.max&.last
=> "CA" 

For Ruby less than 2.3 you can replace &.last with .try(:last) Either one is just a safeguard for if your source hash is empty: {}

JP Duffy
  • 1,307
  • 1
  • 11
  • 18
0

The answers provided assume there would ever be a single largest value. However, it can have duplicates. To return keys of the largest value, including any duplicates, you can use either of the following methods:

  1. Enumerable#select;
  2. Hash#each
# 1: using `Enumerable#select`

def max_value_keys(hash)
  max_value = hash.values.max
  max_values = hash.select { | key, value | value == max_value }
  max_values.keys
end

print max_value_keys({ a: 20, b: 50, c: 30 }) #=> [:b]
print max_value_keys({ a: 20, b: 50, c: 50 }) #=> [:b, :c]
# 2: using `Hash#each`

def max_value_keys(hash)
  max_value = nil
  keys = []

  hash.each do | key, value |
    if max_value.nil? || value > max_value
      max_value = value
      keys = [key]
    elsif value == max_value
      keys << key
    end
  end

  keys
end

print max_value_keys({ a: 20, b: 50, c: 30 }) #=> [:b]
print max_value_keys({ a: 20, b: 50, c: 50 }) #=> [:b, :c]

Wrote a blog post for those interested in learning more.

designcise
  • 4,204
  • 1
  • 17
  • 13
-3

This will return the last key of the hash sorted by size; however, there might be two keys with the same value.

def largest_hash_key(hash)
  key = hash.sort{|a,b| a[1] <=> b[1]}.last
  puts key
end

hash = { "n" => 100, "m" => 100, "y" => 300, "d" => 200, "a" => 0 }
largest_hash_key(hash)
thenengah
  • 42,557
  • 33
  • 113
  • 157
  • 2
    selected answer? may_by is much better than a low-level sort. It's more compact and uses less memory than a sort+last. – tokland May 18 '11 at 07:01