Assistance dynamically building a nested hash

M

Matthew Williams

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.
 
7

7stud --

Matthew said:
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}}
 
G

Gary Wright

#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 Wright
 
J

Jens Wille

Gary Wright [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) }

;-)
h[1][2][3][4] = 5

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

cheers
jens

--
Jens Wille, Dipl.-Bibl. (FH)
prometheus - Das verteilte digitale Bildarchiv für Forschung & Lehre
Kunsthistorisches Institut der Universität zu Köln
Albertus-Magnus-Platz, D-50923 Köln
Tel.: +49 (0)221 470-6668, E-Mail: (e-mail address removed)
http://www.prometheus-bildarchiv.de/
 
M

Matthew Williams

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...
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!
 
M

Matthew Williams

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.
 
A

Aarthi Ruby

Hi,

Can you please post the solutions if you have resolved this? I am kind
of stuck at the same state as yours :-(
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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,982
Messages
2,570,190
Members
46,736
Latest member
zacharyharris

Latest Threads

Top