How to sort a Ruby Hash by number value?
Solution 1
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]]
If you need a hash as a result, you can use to_h
(in Ruby 2.0+)
metrics.sort_by {|_key, value| value}.to_h
# ==> {"siteb.com" => 9, "sitec.com" => 10, "sitea.com", 745}
Solution 2
Since value is the last entry, you can do:
metrics.sort_by(&:last)
Solution 3
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.
Solution 4
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?
Related videos on Youtube
Dustin M.
Updated on July 28, 2020Comments
-
Dustin M. almost 4 years
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.
-
fl00r over 14 yearswhat ruby version do you use? your sort result is very strange
-
-
Mladen Jablanović over 14 yearsor simply
sort_by{|k,v| v}
-
Dustin M. over 14 yearsAhh 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. over 14 yearsMy 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.
-
Jacob Mattison over 14 yearsYup. Occasionally I hear someone refer to Ruby as "untyped". Oh, no, it's definitely typed. It's just not statically typed. :)
-
Hady Elsahar over 11 yearsthis is why i love Ruby ... such problem is pain in a head in other languages. so simple
-
engineerDave about 11 yearsone note is that if your keys are symbols you might have to convert them to strings.
-
Marc-André Lafortune about 11 years@engineerDave: Did you mean if your values are symbols? In any case, that's incorrect as
Symbol
s are comparable to one another. -
engineerDave about 11 years@Marc-AndréLafortune: Not if they can't be coerced to strings? I'm a little stymied on this one. :) Welcoming any clarification. Perhaps a visual example can clarify. gist.github.com/nacengineer/5577868
-
Marc-André Lafortune about 11 years@engineerDave: No idea how you get your results.
h2.sort
works in Ruby 1.9x or 2.0. -
engineerDave about 11 years@Marc-AndréLafortune: nevermind. must have been Gremlins in irb. its working now. thanks!
-
Redoman about 11 yearsdon't forget you get an [] back instead of an {}
-
Elchin over 9 yearsif you want to revert it to hash for, I found the following working:
metrics.sort_by{ |k, v| v }.inject(Hash.new){ |h, a| h.merge!({a[0] => a[1]}) }
-
Marc-André Lafortune over 9 years@Elchin: you can use
metrics.sort_by{ |k, v| v }.reverse.to_h
-
Elchin over 9 years@Marc-AndréLafortune, totally my bad, didn't see #to_h! Thank you!
-
Gerry Gleason about 9 yearsActually even simpler as: hash.sort_by(&:last) with the same caveat about getting an array of pairs vs. a Hash.
-
Tamer Shlash almost 9 yearsThis is awesome! any referecne for the pre-definition of
&:last
? -
lazybios almost 9 yearsHi @Marc-AndréLafortune, I have a small question why add a underscore at begin of key. This coding style mean what?
-
Marc-André Lafortune almost 9 years@lazybios See here: stackoverflow.com/questions/8689673/…
-
lazybios almost 9 years@Marc-AndréLafortune Thank you ! :)
-
Beni Cherniavsky-Paskin almost 7 years
sort_by(&:last)
is effectively shorthand forsort_by {|x| x.last}
stackoverflow.com/questions/1217088/… -
bragboy over 6 yearsfor reverse sort you may use
metrics.sort_by{|k,v| -v}
-
Francisco Quintero over 4 yearsAwesome. I came up with this way which is ugly, IMO
metrics.invert.sort.reverse.to_h.invert
Using the#invert
method ofHash
class