# Sort hash in model

Hi, I have this hash:

hash = { 4049=>[4133, 100], 5814=>[4075, 84], 382543=>[4064, 74],
382544=>[4065, 99], 382545=>[4066, 75] }

I need to sort (DESC) this hash by the second item of array.
Example: 100, 84, 74, 99, 75

How can I solve this problem ? I’m using sort method but can’t work it
out.

Thanks.

On May 29, 2015, at 7:24 AM, Gm [email protected] wrote:

I need to sort (DESC) this hash by the second item of array.
Example: 100, 84, 74, 99, 75

How can I solve this problem ? I’m using sort method but can’t work it out.

You can’t really sort a regular hash—by definition a hash is unordered.
So what output do you want? Possibly an array structured (I’m not
showing it sorted) something like:
[[4049,[4133,100]],[5814,[4075,84]]…]. Rails provides a kind of hybrid
thing, OrderedHash, which you could build—but you’d have to build an
array and then sort it anyway in order to be able to insert items into
an OrderedHash in sort order.

Scott R.
[email protected]
http://www.elevated-dev.com/
(303) 722-0567 voice

sorted_by_second_value = Hash[hash.sort_by
http://ruby-doc.org/core-2.2.2/Enumerable.html#method-i-sort_by { |_,
v|
v[1] }]

For those saying ruby hashes are unordered:

Hashes enumerate their values in the order that the corresponding keys
were
inserted.

sorted_by_second_value
​.map { |_, v| v[1] }
=> [74, 75, 84, 99, 100]

​Paul​

On 2015-May-29, at 09:24 , Gm [email protected] wrote:

Hi, I have this hash:

hash = { 4049=>[4133, 100], 5814=>[4075, 84], 382543=>[4064, 74], 382544=>[4065,
99], 382545=>[4066, 75] }

I need to sort (DESC) this hash by the second item of array.
Example: 100, 84, 74, 99, 75

How can I solve this problem ? I’m using sort method but can’t work it out.

Thanks.

Well, assuming that you know a Hash isn’t really sortable and you’ll end
up with an Array (of Arrays)…

irb2.2.2> hash = { 4049=>[4133, 100], 5814=>[4075, 84], 382543=>[4064,
74], 382544=>[4065, 99], 382545=>[4066, 75] }
#2.2.2 => {4049=>[4133, 100], 5814=>[4075, 84], 382543=>[4064, 74],
382544=>[4065, 99], 382545=>[4066, 75]}
irb2.2.2> hash.sort_by {|k,v| v[1]}
#2.2.2 => [[382543, [4064, 74]], [382545, [4066, 75]], [5814, [4075,
84]], [382544, [4065, 99]], [4049, [4133, 100]]]
irb2.2.2> hash.sort_by {|k,v| v[1]}.reverse
#2.2.2 => [[4049, [4133, 100]], [382544, [4065, 99]], [5814, [4075,
84]], [382545, [4066, 75]], [382543, [4064, 74]]]
irb2.2.2> hash.sort_by {|k,v| -v[1]}
#2.2.2 => [[4049, [4133, 100]], [382544, [4065, 99]], [5814, [4075,
84]], [382545, [4066, 75]], [382543, [4064, 74]]]

You really want Hash#sort_by

-Rob

On Mon, Jun 1, 2015 at 7:03 AM, Gm [email protected] wrote:

Thank you all.

Paul, I end up doing this:

sorted_by_second_value = Hash[hash.sort_by { |_, v| v[1] }]
sorted_by_second_value.to_a.reverse.to_h

​Here you’re converting an array (​hash.sort_by { |_, v| v[1] }) to a
hash (
Hash[…]) then back to an array (.to_a) then reversing and then turning
back into a hash (.to_h).

Assuming you don’t need the intermediate results, you can skip a couple
of
those by just doing,

Hash[hash.sort_by { |_, v| v[1] }.reverse]

or,

hash.sort_by { |_, v| v[1] }.reverse.to_h # if you prefer .to_h

There’s an interesting stackoverflow analysis on ways of descending
order
sorts in Ruby. Summary: sort_by + reverse is the fastest, slightly ahead
of
the -v hack (fewer ops presumably).

Paul

Thank you all.

Paul, I end up doing this:

sorted_by_second_value = Hash[hash.sort_by { |_, v| v[1] }]
sorted_by_second_value.to_a.reverse.to_h

Thanks.