Assistance dynamically building a nested hash

I’ve done some searching and have found some nested hash references but
not quite enough to get me going with what I need.

I’m looking to build a structure like so…

actuals = {actual_id, {date => count, date => count, date => count}}

An example would be like:

actuals = {“1”, {“01-01-2008” => 5, “01-02-2008” => 10}}

Then I can later iterate through the hash and for each ID, get any date
associated with it an associated count.

I’m pulling the data in with an ActiveRecord find that will return a
dozen or so records for a given id but with various dates and counts.

So records returned could look like

1, “01-02-2008”, 5
1, “01-03-2008”, 10
2, “12-25-2007”, 5
1, “01-04-2008”, 15

Should result in a hash when I’m finished like so:

actuals =
{“1”,{“01-02-2008” => 5, “01-03-2008” => 10 “01-04-2008” => 15}},
{“2”,{“12-25-2007” => 5}}

Iterating through those records is no problem… I just can’t wrap my
brain around the nested hash of dates and counts for a given id.

I’m assuming this is the appropriate and most effective data structure
for this data but I would be up for any other suggestions.

I appreciate any responses, thanks.

Matthew W. wrote:

I’ve done some searching and have found some nested hash references but
not quite enough to get me going with what I need.

I’m looking to build a structure like so…

actuals = {actual_id, {date => count, date => count, date => count}}

An example would be like:

actuals = {“1”, {“01-01-2008” => 5, “01-02-2008” => 10}}

Then I can later iterate through the hash and for each ID, get any date
associated with it an associated count.

I’m pulling the data in with an ActiveRecord find that will return a
dozen or so records for a given id but with various dates and counts.

So records returned could look like

1, “01-02-2008”, 5
1, “01-03-2008”, 10
2, “12-25-2007”, 5
1, “01-04-2008”, 15

Should result in a hash when I’m finished like so:

actuals =
{“1”,{“01-02-2008” => 5, “01-03-2008” => 10 “01-04-2008” => 15}},
{“2”,{“12-25-2007” => 5}}

Iterating through those records is no problem… I just can’t wrap my
brain around the nested hash of dates and counts for a given id.

I’m assuming this is the appropriate and most effective data structure
for this data but I would be up for any other suggestions.

I appreciate any responses, thanks.

arr = [
[1, “01-02-2008”, 5],
[1, “01-03-2008”, 10],
[2, “12-25-2007”, 5],
[1, “01-04-2008”, 15]
]

#Create a hash where looking up a non-existent key
#in the hash results in the key being created and
#assigned an empty hash:
results = Hash.new do |hash, key|
hash[key] = {}
end

arr.each do |sub_arr|
main_key = sub_arr[0]
sub_key = sub_arr[1]

#Create new key, value in sub hash:
results[main_key][sub_key] = sub_arr[2]
end

p results

–output:–
{1=>{“01-04-2008”=>15, “01-03-2008”=>10, “01-02-2008”=>5},
2=>{“12-25-2007”=>5}}

On Jan 28, 2008, at 2:51 PM, 7stud – wrote:

#Create a hash where looking up a non-existent key
#in the hash results in the key being created and
#assigned an empty hash:
results = Hash.new do |hash, key|
hash[key] = {}
end

This works for a two-level hash, which is what the OP needed.

If you want an infinite-level hash:

lazy = lambda { |h,k| h[k] = Hash.new(&lazy) }

h = Hash.new(&lazy)

h[1][2][3][4] = 5

p h # {1=>{2=>{3=>{4=>5}}}}

Gary W.

Gary W. [2008-01-28 21:07]:

This works for a two-level hash, which is what the OP needed.

If you want an infinite-level hash:

lazy = lambda { |h,k| h[k] = Hash.new(&lazy) }

h = Hash.new(&lazy)
you can even do it like this:

h = Hash.new { |l, k| l[k] = Hash.new(&l.default_proc) }

:wink:

h[1][2][3][4] = 5

p h # {1=>{2=>{3=>{4=>5}}}}

cheers
jens

I’m trying to work with this code as we speak, I’m still a bit of a Ruby
novice so I’m still getting used to the idioms involved…

7stud – wrote:

arr = [
[1, “01-02-2008”, 5],
[1, “01-03-2008”, 10],
[2, “12-25-2007”, 5],
[1, “01-04-2008”, 15]
]

I’m running .to_a on my ActiveRecord find result set which is properly
making it an array.

#Create a hash where looking up a non-existent key
#in the hash results in the key being created and
#assigned an empty hash:
results = Hash.new do |hash, key|
hash[key] = {}
end

arr.each do |sub_arr|
main_key = sub_arr[0]
sub_key = sub_arr[1]

#Create new key, value in sub hash:
results[main_key][sub_key] = sub_arr[2]
end

Once all of those methods run against my result set I don’t seem to end
up with the result you ended up with. I’m running the debugger against
it and I’m trying to follow the path to nail down why it isn’t exactly
working…

My code:

@actuals = Actual.find(:all, :select => ‘obs_number, week_ending,
labor_hours’, :conditions => [“week_ending >= ? AND project_number = ?
AND primary_number = ?”, @week_ending, @charge.project_number,
@charge.primary_number]).to_a

results = Hash.new do |hash, key|
  hash[key] = {}
end

@actuals.each do |sub_arr|
  main_key = sub_arr[0]
  sub_key = sub_arr[1]
  #Create new key, value in sub hash:
  results[main_key][sub_key] = sub_arr[2]
end

After that runs I’m left with results as a single hash with no data.
I’ll continue with the debugging and hopefully end up with a successful
result soon enough. Thanks for the responses!

p results

–output:–
{1=>{“01-04-2008”=>15, “01-03-2008”=>10, “01-02-2008”=>5},
2=>{“12-25-2007”=>5}}

My code:

@actuals = Actual.find(:all, :select => ‘obs_number, week_ending,
labor_hours’, :conditions => [“week_ending >= ? AND project_number = ?
AND primary_number = ?”, @week_ending, @charge.project_number,
@charge.primary_number]).to_a

results = Hash.new do |hash, key|
  hash[key] = {}
end

@actuals.each do |sub_arr|
  main_key = sub_arr[0]
  sub_key = sub_arr[1]
  #Create new key, value in sub hash:
  results[main_key][sub_key] = sub_arr[2]
end

After that runs I’m left with results as a single hash with no data.
I’ll continue with the debugging and hopefully end up with a successful
result soon enough. Thanks for the responses!

sub_arr was being treated as an actual object data type… So a few
quick changes to sub_arr to reference the attributes instead of indexes
and I’m all set.

I’m still working on my iterator to appropriately sort through them in
my view but I appreciate the help a lot on getting the ball rolling…

Take care.

On Jan 28, 2008, at 3:43 PM, Jens W. wrote:

h = Hash.new { |l, k| l[k] = Hash.new(&l.default_proc) }

slick

Hi,

Can you please post the solutions if you have resolved this? I am kind
of stuck at the same state as yours :frowning:
Appreciate any help.

Thanks much!

My code:

@actuals = Actual.find(:all, :select => ‘obs_number, week_ending,
labor_hours’, :conditions => [“week_ending >= ? AND project_number = ?
AND primary_number = ?”, @week_ending, @charge.project_number,
@charge.primary_number]).to_a

results = Hash.new do |hash, key|
  hash[key] = {}
end

@actuals.each do |sub_arr|
  main_key = sub_arr[0]
  sub_key = sub_arr[1]
  #Create new key, value in sub hash:
  results[main_key][sub_key] = sub_arr[2]
end

After that runs I’m left with results as a single hash with no data.
I’ll continue with the debugging and hopefully end up with a successful
result soon enough. Thanks for the responses!

sub_arr was being treated as an actual object data type… So a few
quick changes to sub_arr to reference the attributes instead of indexes
and I’m all set.

I’m still working on my iterator to appropriately sort through them in
my view but I appreciate the help a lot on getting the ball rolling…

Take care.