# How does one sort hash of hashes by multiple values?

Discussion in 'Ruby' started by joe.yakich@gmail.com, Nov 5, 2005.

1. ### Guest

Imagine I have this data structure:

@my_hash[8858]['name'] = 'goober'
@my_hash[8858]['sort_date'] = 19991231

@my_hash[2004]['name'] = 'goober'
@my_hash[2004]['sort_date'] = '20010416'

@my_hash[8872]['name'] = 'pyle'
@my_hash[8872]['sort_date'] = '20010416'

@my_hash[89]['name'] = 'hogan'
@my_hash[89]['sort_date'] = '2004 0918'

@my_hash[9]['name'] = 'homer'
@my_hash[9]['sort_date'] = '19980718'

How does one sort it first by the name value, then by the sort_date
value? (So that the name == 'goober' items appear before the others,
and the very first element returned by the sort would be
@my_hash[8858]?)

I tried searching a bit (the FAQ and google) , but came up empty; sorry
if this is a noob question. (Although, I am a ruby noob, so...)

TIA!

Joe

, Nov 5, 2005

2. ### zdennisGuest

wrote:
> Imagine I have this data structure:
>
> @my_hash[8858]['name'] = 'goober'
> @my_hash[8858]['sort_date'] = 19991231
>
> @my_hash[2004]['name'] = 'goober'
> @my_hash[2004]['sort_date'] = '20010416'
>
> @my_hash[8872]['name'] = 'pyle'
> @my_hash[8872]['sort_date'] = '20010416'
>
> @my_hash[89]['name'] = 'hogan'
> @my_hash[89]['sort_date'] = '2004 0918'
>
> @my_hash[9]['name'] = 'homer'
> @my_hash[9]['sort_date'] = '19980718'
>
> How does one sort it first by the name value, then by the sort_date
> value? (So that the name == 'goober' items appear before the others,
> and the very first element returned by the sort would be
> @my_hash[8858]?)
>
> I tried searching a bit (the FAQ and google) , but came up empty; sorry
> if this is a noob question. (Although, I am a ruby noob, so...)
>

There is probably a cleaner way to do this but...

sorted_keys = @my_hash.keys.sort do |a,b|
next result unless res=(@my_hash[a]['name']<=>@my_hash['name']) == 0
@my_hash[a]['sort_date']<=>@my_hash['sort_date']
end

Then since you have your sorted keys you can iterate over each item based on your sorted_keys array.

Zach

zdennis, Nov 5, 2005

3. ### zdennisGuest

zdennis wrote:
> wrote:
>
>> Imagine I have this data structure:
>>
>> @my_hash[8858]['name'] = 'goober'
>> @my_hash[8858]['sort_date'] = 19991231
>>
>> @my_hash[2004]['name'] = 'goober'
>> @my_hash[2004]['sort_date'] = '20010416'
>>
>> @my_hash[8872]['name'] = 'pyle'
>> @my_hash[8872]['sort_date'] = '20010416'
>>
>> @my_hash[89]['name'] = 'hogan'
>> @my_hash[89]['sort_date'] = '2004 0918'
>>
>> @my_hash[9]['name'] = 'homer'
>> @my_hash[9]['sort_date'] = '19980718'
>>
>> How does one sort it first by the name value, then by the sort_date
>> value? (So that the name == 'goober' items appear before the others,
>> and the very first element returned by the sort would be
>> @my_hash[8858]?)
>>
>> I tried searching a bit (the FAQ and google) , but came up empty; sorry
>> if this is a noob question. (Although, I am a ruby noob, so...)
>>

>
> There is probably a cleaner way to do this but...
>
> sorted_keys = @my_hash.keys.sort do |a,b|
> next result unless res=(@my_hash[a]['name']<=>@my_hash['name']) == 0
> @my_hash[a]['sort_date']<=>@my_hash['sort_date']
> end

That should be:

sorted_keys = @my_hash.keys.sort do |a,b|
next result unless result=(@my_hash[a]['name']<=>@my_hash['name']) == 0
@my_hash[a]['sort_date']<=>@my_hash['sort_date']
end

zdennis, Nov 5, 2005
4. ### William JamesGuest

wrote:
> Imagine I have this data structure:
>
> @my_hash[8858]['name'] = 'goober'
> @my_hash[8858]['sort_date'] = 19991231
>
> @my_hash[2004]['name'] = 'goober'
> @my_hash[2004]['sort_date'] = '20010416'
>
> @my_hash[8872]['name'] = 'pyle'
> @my_hash[8872]['sort_date'] = '20010416'
>
> @my_hash[89]['name'] = 'hogan'
> @my_hash[89]['sort_date'] = '2004 0918'
>
> @my_hash[9]['name'] = 'homer'
> @my_hash[9]['sort_date'] = '19980718'
>
> How does one sort it first by the name value, then by the sort_date
> value? (So that the name == 'goober' items appear before the others,
> and the very first element returned by the sort would be
> @my_hash[8858]?)
>
> I tried searching a bit (the FAQ and google) , but came up empty; sorry
> if this is a noob question. (Although, I am a ruby noob, so...)
>
> TIA!
>
> Joe

require 'pp'

my_hash = Hash.new { |hash, key| hash[key] = Hash.new }

my_hash[8858]['name'] = 'goober'
my_hash[8858]['sort_date'] = '19991231'

my_hash[2004]['name'] = 'goober'
my_hash[2004]['sort_date'] = '20010416'

my_hash[8872]['name'] = 'pyle'
my_hash[8872]['sort_date'] = '20010416'

my_hash[89]['name'] = 'hogan'
my_hash[89]['sort_date'] = '20040918'

my_hash[9]['name'] = 'homer'
my_hash[9]['sort_date'] = '19980718'

pp my_hash.sort_by{|x| [ x.last['name'], x.last['sort_date'] ] }

---------------------------->

[[8858, {"name"=>"goober", "sort_date"=>"19991231"}],
[2004, {"name"=>"goober", "sort_date"=>"20010416"}],
[89, {"name"=>"hogan", "sort_date"=>"20040918"}],
[9, {"name"=>"homer", "sort_date"=>"19980718"}],
[8872, {"name"=>"pyle", "sort_date"=>"20010416"}]]

William James, Nov 5, 2005