Hash of Hash of Arrays Question

Hi all,

I decided to take a deep look into hashes today and how hashes of arrays
are handled. This is a bit of a grasp for me because most of the
languages I’ve worked with, arrays are handled in just a few ways. With
Ruby, it’s much better.

So, here are my questions using an example scenario I’m creating from
scratch.

Creating a new Hash:

myhash = Hash.new {|h,k| h[k] = {} }
myhash.class
=> Hash

Creating two Arrays:

mykeyarray = Array.
=> [1, 2, 3, 4, 5]

myvaluearray = Array.
=> [10, 20, 30, 40, 50]

5.times do |i|
myhash[mykeyarray[i]][:numbers] = myvaluearray[i]
end

myhash.keys
=> [5, 1, 2, 3, 4]

myhash.values
=> [{:numbers=>50}, {:numbers=>10}, {:numbers=>20}, {:numbers=>30},
{:numbers=>40}]

myhash.inspect
=> “{5=>{:numbers=>50}, 1=>{:numbers=>10}, 2=>{:numbers=>20},
3=>{:numbers=>30}, 4=>{:numbers=>40}}”

So, I would believe that this is a hash of hashes of arrays correct?

Secondly, how would I parse information out of this hash? Creating them
is easy. Extracting exactly the way I want - not so easy.

Let me give you an example:

I create a constant that stores the symbol I want to use for my table.

MY_TABLE_FIELD = [:numbers]

myhash.each do |key|
values = {:compiled_on => Date.today.strftime(’%Y-%m-%d’)}
MY_TABLE_FIELD.each_with_index do |field, i|
values[field] = key[i]
end
model.create values
end

… this won’t work …

I want to match the symbol in my hash with the symbol in my constant
(which represents the table field). I want to update the table field
with the value of the hash (10,20,30,40,50). They hash key would
represent the id field (1,2,3,4,5).

How can I accomplish this given the information provided?

I performed the following test which got some of the results from this
hash of hashes…

myhash.each_pair do |k,v|
puts “My key is #{k}.”
v.each_pair do |key, value|
puts “Inner Key = #{key} and Inner Value = #{value}”
end
end

returns…

My key is 5.
Inner Key = numbers and Inner Value = 50
My key is 5numbers50.
My key is 3numbers30.
My key is 1.
Inner Key = numbers and Inner Value = 10
My key is .
My key is 4numbers40.
My key is 2.
Inner key = numbers and Inner Value = 20
My key is 1numbers10.
My key is 3.
Inner key = numbers and Inner Value = 30
My key is 4.
Inner Key = numbers and Inner Value = 40
My key is 2numbers20.

I don’t want this…

I want…

My key is 5.
Inner Key = numbers and Inner Value = 50
My key is 1.
Inner Key = numbers and Inner Value = 10
My key is 2.
Inner key = numbers and Inner Value = 20
My key is 3.
Inner key = numbers and Inner Value = 30
My key is 4.
Inner Key = numbers and Inner Value = 40

Okay, I was pretty close…

I figured this part out:

myhash.each_pair do |k,v|
v.each_pair do |key, value|
puts “Key = #{k} and Inner Key = #{key} and Inner Value = #{value}”
end
end

Returns:

Key = 5 and Inner Key = numbers and Inner Value = 50
Key = 1 and Inner Key = numbers and Inner Value = 10
Key = 2 and Inner Key = numbers and Inner Value = 20
Key = 3 and Inner Key = numbers and Inner Value = 30
Key = 4 and Inner Key = numbers and Inner Value = 40

So, that answers one part of my question…

Now I have to figure out how to match this up to my constant fields…

Well I’ve spent several hours on this and can’t figure out how to get
everything matched up. I think the issue really comes down to the
constant is an array of values and I’m comparing it to a hash which is a
paired key+value…

Therefore, I would probably have to convert my constant to a hash before
using it with this.

In any event, I’ll stick with my original method although it’s quite a
bit sloppy looking…

But,…

myhash.each_pair do |k,v|
v.each_pair do |key, value|
puts “Key = #{k} and Inner Key = #{key} and Inner Value = #{value}”
end
end

Does find exactly what I need for any future needs when required. So,
at least I learned something. Now if I could just figure out how to
sort a hash…

Thanks Gary,

I’d much rather be using 1.9.1 but unfortunately I have to stay with 1.8
for now. I’ll eventually make the switch when some gems/plugins I use
move forward.

Thanks!

On Jul 18, 2009, at 12:43 PM, Älphä Blüë wrote:

Does find exactly what I need for any future needs when required. So,
at least I learned something. Now if I could just figure out how to
sort a hash…

Prior to Ruby 1.9, hashes are unsorted. In Ruby 1.9, hashes are
maintained in insertion order. That is to say, if you iterate
over the hash you’ll get the key/value pairs in the order in
which they were inserted into the hash.

If you want to iterate over a hash according to some other
order you’ll need to do something like:

hash = {2=>1, 1=>0, 3=>4}

hash.sort_by {|k,v| k }.each { |k,v|
puts “key: #{k}, value: #{v}”
}

key: 1, value: 0
key: 2, value: 1
key: 3, value: 4

Note that sort_by doesn’t return a hash but instead returns
an array of key/value pairs:

hash.sort_by { |k,v| v }
=> [[1, 0], [2, 1], [3, 4]]

Gary W.