[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Assistance dynamically building a nested hash

Matthew Williams

1/28/2008 7:07:00 PM

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.
--
Posted via http://www.ruby-....

6 Answers

7stud --

1/28/2008 7:51:00 PM

0

Matthew Williams 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}}
--
Posted via http://www.ruby-....

Gary Wright

1/28/2008 8:07:00 PM

0


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 Wright


Jens Wille

1/28/2008 8:43:00 PM

0

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: jens.wille@uni-koeln.de
http://www.prometheus-bild...

Matthew Williams

1/28/2008 8:56:00 PM

0

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

--
Posted via http://www.ruby-....

Gary Wright

1/28/2008 9:09:00 PM

0


On Jan 28, 2008, at 3:43 PM, Jens Wille wrote:
> h = Hash.new { |l, k| l[k] = Hash.new(&l.default_proc) }

slick

Matthew Williams

1/28/2008 9:26:00 PM

0

>
> 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.
--
Posted via http://www.ruby-....