tags:

views:

194

answers:

3

Hi everyone,

I have a counter hash that I am trying to sort by count. The problem I am running into is that the default Hash.sort function sorts numbers like strings rather than by number size.

i.e. Given Hash:

metrics = {"sitea.com" => 745, "siteb.com" => 9, "sitec.com" => 10 }

Running this code:

metrics.sort {|a1,a2| a2[1]<=>a1[1]}

will return a sorted array:

[ 'siteb.com', 9, 'sitea.com', 745, 'sitec.com', 10]

Even though 745 is a larger number than 9, 9 will appear first in the list. When trying to show who has the top count, this is making my life difficult. :)

Any ideas on how to sort a hash (or an array even) by number value size?

I appreciate any help.

+5  A: 

No idea how you got your results, since it would not sort by string value... You should reverse a1 and a2 in your example

Best way in any case (as per Mladen) is:

metrics = {"sitea.com" => 745, "siteb.com" => 9, "sitec.com" => 10 }
metrics.sort_by {|key, value| value}
  # ==> [["siteb.com", 9], ["sitec.com", 10], ["sitea.com", 745]]
Marc-André Lafortune
or simply `sort_by{|k,v| v}`
Mladen Jablanović
indeed... Answer udpated :-)
Marc-André Lafortune
My number was returning as a string, that fixed it.. I had a2 and a1 in that order because I wanted the results to sort decending.. thanks for your feedback though.
Dustin M.
+3  A: 

That's not the behavior I'm seeing:

irb(main):001:0> metrics = {"sitea.com" => 745, "siteb.com" => 9, "sitec.com" =>
 10 }
=> {"siteb.com"=>9, "sitec.com"=>10, "sitea.com"=>745}
irb(main):002:0> metrics.sort {|a1,a2| a2[1]<=>a1[1]}
=> [["sitea.com", 745], ["sitec.com", 10], ["siteb.com", 9]]

Is it possible that somewhere along the line your numbers are being converted to strings? Is there more code you're not posting?

JacobM
Ahh your right it looks like the result in my code was returning it as a string. Pesky data types. :) Sometimes I am just too close to the problem.Thanks.
Dustin M.
Yup. Occasionally I hear someone refer to Ruby as "untyped". Oh, no, it's definitely typed. It's just not statically typed. :)
JacobM
A: 

Already answered but still. Change your code to:

metrics.sort {|a1,a2| a2[1].to_i <=> a1[1].to_i }

Converted to strings along the way or not, this will do the job.

dimitko