Key Associated w/ Maximum Value in Hash

Simple question: what’s the cleanest way to retrieve a key associated
with the maximum value of a hash. For instance, how do I retrieve ‘b’
from the following example:

hash = Hash.new
hash[‘a’]=4
hash[‘b’]=10
hash[‘c’]=7

On Wed, Sep 8, 2010 at 9:57 PM, Timothy B.
[email protected]wrote:

How about Enumerable#max

hash = {‘a’=>4,‘b’=>10,‘c’=>7}
max_record = hash.max { |a,b| a.last <=> b.last } # => [“b”, 10]
max_index = max_record && max_record.first # => “b”

On 09.09.2010 05:23, Josh C. wrote:


Posted via http://www.ruby-forum.com/.

How about Enumerable#max

hash = {‘a’=>4,‘b’=>10,‘c’=>7}
max_record = hash.max { |a,b| a.last<=> b.last } # => [“b”, 10]
max_index = max_record&& max_record.first # => “b”

In 1.9.x you can even spare the #last:

irb(main):001:0> hash = {‘a’=>4,‘b’=>10,‘c’=>7}
=> {“a”=>4, “b”=>10, “c”=>7}
irb(main):002:0> hash.max {|(k1,v1),(k2,v2)| v1 <=> v2}
=> [“b”, 10]

Here’s a version with #inject

irb(main):004:0> hash.inject([nil,0]) {|(maxk,maxv),(k,v)| v > maxv ?
[k,v] : [maxk,maxv]}.last
=> 10

Kind regards

robert

On Thu, Sep 9, 2010 at 11:57 AM, Timothy B. [email protected]
wrote:

Simple question: what’s the cleanest way to retrieve a key associated
with the maximum value of a hash. For instance, how do I retrieve ‘b’
from the following example:

hash = Hash.new
hash[‘a’]=4
hash[‘b’]=10
hash[‘c’]=7

What if you have more than one max?

h = {‘a’=>4,‘b’=>10,‘c’=>7,‘d’ => 10}

p h.select{|x,i| i==h.values.max}.keys #> [“b”, “d”]

Harry

hash.sort_by { |k,v| v }[-1][0]

This won’t capture multiple maximum values, but:

hash.invert[hash.values.max]

I’d be interested to see a benchmark profile of the suggestions.

I’ve tried several of these approaches, and they all work well. I’m
curious, too, about which is the fastest, but for my small hashs,
there’s no noticable difference.

Adam P. wrote:

This won’t capture multiple maximum values, but:

hash.invert[hash.values.max]

I’d be interested to see a benchmark profile of the suggestions.

On Sep 9, 2010, at 23:00, Timothy B. wrote:

I’ve tried several of these approaches, and they all work well. I’m
curious, too, about which is the fastest, but for my small hashs,
there’s no noticable difference.

Don’t bother optimizing it for speed unless you are sure it’s a
bottleneck. Choose whichever option is the most readable and
maintainable.

Ben

For fun:

http://www.pastie.org/1153968

$ ruby -v
ruby 1.9.1p378 (2010-01-10 revision 26273) [x86_64-linux]
$ ruby max_hash_value.rb
{0=>-18, 1=>-5, 2=>-31, 3=>44, 4=>-13, 5=>-1, 6=>23, 7=>5, 8=>22, 9=>37}
user system total
real
max 0.110000 0.000000 0.110000 (
0.270811)
max 1.9.X 0.090000 0.000000 0.090000 (
0.242181)
select 0.430000 0.000000 0.430000 (
1.270329)
select (cache max) 0.080000 0.000000 0.080000 (
0.147179)
sort_by 0.160000 0.000000 0.160000 (
0.438671)
invert 0.080000 0.000000 0.080000 (
0.279259)
invert (cache max) 0.060000 0.000000 0.060000 (
0.155440)

On Thu, Sep 9, 2010 at 2:25 AM, Robert K.
[email protected] wrote:

Here’s a version with #inject

irb(main):004:0> hash.inject([nil,0]) {|(maxk,maxv),(k,v)| v > maxv ? [k,v]
: [maxk,maxv]}.last
=> 10

But that fails if there are only negative values in the hash.

hash = {:a => -2, :b => -4}
hash.inject([nil,0]) {|(maxk,maxv),(k,v)| v > maxv ? [k,v] :
[maxk,maxv]}.last # => 0


Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Github: rubyredrick (Rick DeNatale) · GitHub
Twitter: @RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale

On 12 September 2010 18:29, Douglas S. [email protected] wrote:

For fun:
http://www.pastie.org/1153968

To keep the fun going :slight_smile:

I wonder why nobody used Enumerable#max_by or Hash#key (#index in 1.8):
HASH.max_by(&:last).first
HASH.key HASH.values.max
And it reveals there are both relatively efficient.

I could not help to DRY a bit the tests :wink:

Regards,
B.D.