Finding highest value in a Hash


#1

I have a hash where the values are numbers. After I build the hash I
want to get the key back that has the largest number as a value.

So for example:

I build the hash and add to the values -

results = Hash.new(0)
score = find_score
score.points.each do |point|
  result_score = ResultScore.find(:first, point)
  if results.has_key?(result_score.result_id)
    results[result_score.result_id] =+ result_score_points
  else
    results[result_score.result_id] = result_score_points
  end
end

Now what I want to do is get the key back out of the hash ‘results’ with
the highest value.

I thought about inverting the hash and then sorting the keys. Does ruby
sort integers as keys?


#2

You can use the max method on hash objects, but it’s usage is a little
odd.

Let’s say your hash is h. This returns the key for the highest value:

h.max { |a,b| a.last <=> b.last }.first

Looks crazy, I know, but it should work. If you want the gory details
of what it’s doing, just let me know. :slight_smile:

Jeff
softiesonrails.com

On Apr 3, 8:19 pm, Arch S. removed_email_address@domain.invalid


#3

I did find a bug in my logic though . . .

If the key already exists, then I want to add to the value. Currently
that is not happening, but rather the value is being replaced:

1  if results.has_key?(result_score.result_id)
2    results[result_score.result_id] =+ result_score_points
3  else
4    results[result_score.result_id] = result_score_points
5  end

See line 2. I’m obviously not using the Ruby syntax correctly.

I replace line 2 with

results[result_score.result_id] = results[result_score.result_id] +
result_score.points

This works, but isn’t elegant.


#4

Arch S. wrote:

Jeff C. wrote:

You can use the max method on hash objects, but it’s usage is a little
odd.

Let’s say your hash is h. This returns the key for the highest value:

h.max { |a,b| a.last <=> b.last }.first

Looks crazy, I know, but it should work. If you want the gory details
of what it’s doing, just let me know. :slight_smile:

Jeff
softiesonrails.com

On Apr 3, 8:19 pm, Arch S. removed_email_address@domain.invalid

Cool - that worked. It looks to me like it’s a short cut for defining a
Comparator?

I did find a bug in my logic though . . .

If the key already exists, then I want to add to the value. Currently
that is not happening, but rather the value is being replaced:

1  if results.has_key?(result_score.result_id)
2    results[result_score.result_id] =+ result_score_points
3  else
4    results[result_score.result_id] = result_score_points
5  end

See line 2. I’m obviously not using the Ruby syntax correctly.

The operator your looking for is written “+=” as opposed to your “=+”.
I have a horrible time remembering which way around the “fancy”
assignment operators go so I have learned to check them when I bug
occurs.

JFM


#5

Jeff C. wrote:

You can use the max method on hash objects, but it’s usage is a little
odd.

Let’s say your hash is h. This returns the key for the highest value:

h.max { |a,b| a.last <=> b.last }.first

Looks crazy, I know, but it should work. If you want the gory details
of what it’s doing, just let me know. :slight_smile:

Jeff
softiesonrails.com

On Apr 3, 8:19 pm, Arch S. removed_email_address@domain.invalid

Cool - that worked. It looks to me like it’s a short cut for defining a
Comparator?

I did find a bug in my logic though . . .

If the key already exists, then I want to add to the value. Currently
that is not happening, but rather the value is being replaced:

1  if results.has_key?(result_score.result_id)
2    results[result_score.result_id] =+ result_score_points
3  else
4    results[result_score.result_id] = result_score_points
5  end

See line 2. I’m obviously not using the Ruby syntax correctly.


#6

Thanks Jeff and Jim - everything is working as planned now.