Sort hash in model

28 views
Skip to first unread message

Gm

unread,
May 29, 2015, 9:24:53 AM5/29/15
to rubyonra...@googlegroups.com
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.


Scott Ribe

unread,
May 29, 2015, 10:25:48 AM5/29/15
to rubyonra...@googlegroups.com, Gm
On May 29, 2015, at 7:24 AM, Gm <javap...@gmail.com> 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 Ribe
scott...@elevated-dev.com
http://www.elevated-dev.com/
https://www.linkedin.com/in/scottribe/
(303) 722-0567 voice





Rob Biedenharn

unread,
May 29, 2015, 11:52:55 AM5/29/15
to rubyonra...@googlegroups.com
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

Paul Makepeace

unread,
May 29, 2015, 5:14:53 PM5/29/15
to rubyonra...@googlegroups.com
sorted_by_second_value = Hash[hash.sort_by { |_, v| v[1] }]

For those saying ruby hashes are unordered: http://ruby-doc.org/core-2.2.2/Hash.html

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​


--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-ta...@googlegroups.com.
To post to this group, send email to rubyonra...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/rubyonrails-talk/3ea488c8-cd97-4f03-b31e-f27b44c009ee%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Gm

unread,
Jun 1, 2015, 10:03:45 AM6/1/15
to rubyonra...@googlegroups.com
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.

Paul Makepeace

unread,
Jun 1, 2015, 4:29:04 PM6/1/15
to rubyonra...@googlegroups.com
On Mon, Jun 1, 2015 at 7:03 AM, Gm <javap...@gmail.com> 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). http://stackoverflow.com/a/2651028/683947

Paul


Reply all
Reply to author
Forward
0 new messages