Reputation: 13475
I'll attempt to illustrate this with an example. Take a common example of a Hash of Hashes:
my %HoH = (
flintstones => {
lead => "fred",
pal => "barney",
},
jetsons => {
lead => "george",
wife => "jane",
"his boy" => "elroy",
},
simpsons => {
lead => "homer",
wife => "marge",
kid => "bart",
},
);
For my purposes, I would like to be able to add an unnamed, or anonymous hashes to %HOH. I won't need (or be able to) define these sub-hashes until runtime. How can I accomplish this with Perl?
Everything I've read (and I have read through Perldocs and Google'd already) seems to show examples where all sub-hahes (e.g. "flintstones", "jetsons", and "simpsons") are defined.
What I am doing is attempting to build a parent Hash that will contain sub-hashes with rows from a CSV file:
%TopHash = (
%Line1 => {
cell01 => $some_value1a;
cell02 => $some_value2a;
cell03 => $some_value3a;
},
%Line2 => {
cell01 => $some_value1b;
cell02 => $some_value2b;
cell03 => $some_value3b;
},
%Line3 => {
cell01 => $some_value1c;
cell02 => $some_value2c;
cell03 => $some_value3c;
},
# etc
# etc
# etc
);
The number of "%LineX" hashes that I need is not known until runtime (because they represent the number of lines in a CSV that is read at runtime).
Any ideas? If it isn't clear already...I still am trying to wrap my head around Perl hashes.
Upvotes: 0
Views: 2821
Reputation: 118605
Everytime you create a new hash from a line of data, you'll need to think of a unique key to store that data in your top hash table.
my $line = 1;
my %HoH;
while (<>) {
my ($cell01, $cell02, $cell03, @etc) = split /,/;
my $newHash = { cell01 => $cell01, cell02 => $cell02, ... };
my $key = "line$line";
$HoH{$key} = $newHash;
$line++;
}
Now keys(%HoH)
will return a (unsorted) list like "line1","line2","line3",...
.
$HoH{"line5"}
would return a reference to the data for the 5th line of your file.
%{$HoH{"line7"}}
is kind of ugly syntax but it returns a hashtable of your data
from line 7.
$HoH{"line14"}{"cell02"}
could be used to get at a specific piece of data.
Upvotes: 0
Reputation: 28227
#!/usr/bin/perl
use strict;
my %HoH = (
line01 => {
cell01 => "cell0101",
cell02 => "cell0102",
cell03 => "cell0103"
}
);
$HoH{"line02"} =
{
cell01 => "cell0201",
cell02 => "cell0202",
cell03 => "cell0203"
};
foreach my $hohKey (keys %HoH)
{
my $newHash = $HoH{$hohKey};
print "Line Name: $hohKey\n";
foreach my $key (keys %$newHash)
{
print "\t$key => ", $newHash->{$key}, "\n";
}
}
Upvotes: 1
Reputation: 42677
First you create the hash from the current line you're parsing
my %lineHash = (
cell01 => $some_value1a,
cell02 => $some_value1b,
cell03 => $some_value1c
);
or create a reference to a hash outright
my $lineHashRef = {
cell01 => $some_value2a,
cell02 => $some_value2b,
cell03 => $some_value2c
};
Then you add it to your overall hash, remembering that nested perl structures just contain references to the other structures.
$topHash{line1} = \%lineHash;
$topHash{line2} = $lineHashRef;
Updated Example given a loop over an array of data to parse
my %topHash;
foreach my $i (0 .. $#data) {
my %tempHash;
// stuff here to parse $data[$i] and populate %tempHash
$topHash{"line$i"} = \%tempHash;
}
Upvotes: 1
Reputation: 66978
To add an anonymous hash at runtime, assign it as you would a normal hash element:
$HoH{key} = { foo => 42 };
or
$HoH{key} = $hash_ref;
or
$HoH{key} = \%hash;
Upvotes: 3