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

···

--
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"

···

On Wed, Sep 8, 2010 at 9:57 PM, Timothy Baron <timothy.baron@gmail.com>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
--
Posted via http://www.ruby-forum.com/\.

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

···

On Thu, Sep 9, 2010 at 11:57 AM, Timothy Baron <timothy.baron@gmail.com> 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
--

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

···

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

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 09.09.2010 05:23, Josh Cheek wrote:

On Wed, Sep 8, 2010 at 9:57 PM, Timothy Baron<timothy.baron@gmail.com>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
--
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"

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

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 Thu, Sep 9, 2010 at 4:37 PM, Brian Candler <b.candler@pobox.com> wrote:

hash.sort_by { |k,v| v }[-1][0]
--
Posted via http://www.ruby-forum.com/\.

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

···

On Thu, Sep 9, 2010 at 2:25 AM, Robert Klemme <shortcutter@googlemail.com> 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

--
Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Github: http://github.com/rubyredrick
Twitter: @RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale

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 Prescott 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.

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

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

···

On Sep 9, 2010, at 23:00, Timothy Baron 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.

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 Fri, Sep 10, 2010 at 5:20 AM, Ben Giddings <bg-rubytalk@infofiend.com>wrote:

On Sep 9, 2010, at 23:00, Timothy Baron 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

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.

···

On 12 September 2010 18:29, Douglas Seifert <doug@dseifert.net> wrote:

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