capriguy84 has asked for the wisdom of the Perl Monks concerning the following question:
I am trying to construct a Hashes of Hashes of Arrays like below.
%HoH = (
flintstones => {
lead => "fred",
pal => "[ "george", "jane", "elroy" ],
},
jetsons => {
lead => "george",
wife => [ "george", "jane", "elroy" ],
boy => [ "george", "jane", "elroy" ],
},
simpsons => {
lead => "homer",
wife => [ "george", "jane", "elroy" ],
kid => [ "george", "jane", "elroy" ],
},
);
I tried to use below code, but it resulted in creating multiple same-key-values and did not actually create an array. What am I doing wrong?
$HOH{$key}{"name"} = $value;
push(@{$HOH{$key}{"price"}}, $value2);
Re: Hashes of Hashes of Arrays? Is it possible?
by liverpole (Monsignor) on Sep 08, 2011 at 18:49 UTC
|
Hi capriguy84,
Looks to me like you've got a simple typo ... first you called the data structure %HOH, then later you referred to it as %HoH. One other typo in your code is the extra quotation mark (or "double quotes" character) on this line:
pal => "[ "george", "jane", "elroy" ],
Fixing those 2 things, giving explicit values for $key and $value, and using Data::Dumper to check the results:
use strict;
use warnings;
use Data::Dumper;
my %HoH = (
flintstones => {
lead => "fred",
pal => [ "george", "jane", "elroy" ],
},
jetsons => {
lead => "george",
wife => [ "george", "jane", "elroy" ],
boy => [ "george", "jane", "elroy" ],
},
simpsons => {
lead => "homer",
wife => [ "george", "jane", "elroy" ],
kid => [ "george", "jane", "elroy" ],
},
);
my $key = 'flintstones';
my $value = 'Wilma';
printf "Before: %s\n", Dumper(\%HoH);
$HoH{$key}{"name"} = $value;
printf " After: %s\n", Dumper(\%HoH);
__END__
Output (Note that 'Wilma' was successfully added):
Before: $VAR1 = {
'simpsons' => {
'kid' => [
'george',
'jane',
'elroy'
],
'lead' => 'homer',
'wife' => [
'george',
'jane',
'elroy'
]
},
'jetsons' => {
'lead' => 'george',
'wife' => [
'george',
'jane',
'elroy'
],
'boy' => [
'george',
'jane',
'elroy'
]
},
'flintstones' => {
'lead' => 'fred',
'pal' => [
'george',
'jane',
'elroy'
]
}
};
After: $VAR1 = {
'simpsons' => {
'kid' => [
'george',
'jane',
'elroy'
],
'lead' => 'homer',
'wife' => [
'george',
'jane',
'elroy'
]
},
'jetsons' => {
'lead' => 'george',
'wife' => [
'george',
'jane',
'elroy'
],
'boy' => [
'george',
'jane',
'elroy'
]
},
'flintstones' => {
'lead' => 'fred',
'name' => 'Wilma',
'pal' => [
'george',
'jane',
'elroy'
]
}
};
s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/
| [reply] [d/l] [select] |
|
Thanks for your reply. I am reading a CSV file(below) and creating a temporary complex hash structure as described to perform some operations. As you can see my $key is the time which should be only one per second and plug the data as hash/array.
NAME,06/01/2011,09:30:00,16.76,756,Q,00
NAME,06/01/2011,09:30:00,16.76,300,Q,00
NAME,06/01/2011,09:30:00,16.76,100,Q,00
NAME,06/01/2011,09:30:01,16.76,100,Q,00
NAME,06/01/2011,09:30:01,16.76,200,Z,00
NAME,06/01/2011,09:30:02,16.77,200,X,00
NAME,06/01/2011,09:30:02,16.77,200,X,00
Open 100k line CSV file and read using Text_CSV. I have to undef the hashes before jumping to next second.
my $csv = Text::CSV_XS->new();
open (FILE, "<", "$tickdir/$file") or die "Can't open CSV File:$!
+\n";
while (<FILE>) {
$csv->parse($_);
my @columns = $csv->fields();
my $key = str2time($columns[1].' '.$columns[2]);
my (@prices, @volumes) = ();
my %HOH = ();
$HOH{$key}{"name"} = $columns[0];
push(@{$HOH{$key}{"price"}}, $columns[3]);
push(@{$HOH{$key}{"volumes"}}, $columns[4]);
print Dumper(\%HOH);
}
close FILE;
OUTPUT: As you can see the key values are same.
$VAR1 = {
'1306935005' => {
'volumes' => [
'200'
],
'name' => 'NAME',
'price' => [
'16.76'
]
}
};
$VAR1 = {
'1306935005' => {
'volumes' => [
'400'
],
'name' => 'NAME',
'price' => [
'16.76'
]
}
};
| [reply] [d/l] [select] |
|
You are overwriting your hash every time through the while loop. Move the declaration of the hash outside of the loop:
my $csv = Text::CSV_XS->new();
open (FILE, "<", "$tickdir/$file") or die "Can't open CSV File:$!
+\n";
my %HOH;
while (<FILE>) {
$csv->parse($_);
my @columns = $csv->fields();
my $key = str2time($columns[1].' '.$columns[2]);
my (@prices, @volumes) = ();
$HOH{$key}{"name"} = $columns[0];
push(@{$HOH{$key}{"price"}}, $columns[3]);
push(@{$HOH{$key}{"volumes"}}, $columns[4]);
print Dumper(\%HOH);
}
close FILE;
| [reply] [d/l] |
|
|
|
|
|
Re: Hashes of Hashes of Arrays? Is it possible?
by toolic (Bishop) on Sep 08, 2011 at 18:43 UTC
|
You seem to be on the right track. What is your expected output?
use warnings;
use strict;
use Data::Dumper;
$Data::Dumper::Sortkeys = 1;
my %HOH;
my $key = 'foo';
my $value = 5;
my $value2 = 6;
$HOH{$key}{"name"} = $value;
push(@{$HOH{$key}{"price"}}, $value2);
push(@{$HOH{$key}{"price"}}, 99);
print Dumper(\%HOH);
__END__
$VAR1 = {
'foo' => {
'name' => 5,
'price' => [
6,
99
]
}
};
That shows an array of prices.
perldsc | [reply] [d/l] |
Re: Hashes of Hashes of Arrays? Is it possible?
by Kc12349 (Monk) on Sep 08, 2011 at 18:49 UTC
|
See my similar code below and it's output from dumping the data. Give us a large sample of your code and run a dump using Data::Dumper or a similar module to show us the data structure generated. You'll be able to get a little more help then.
my %HOH;
$HOH{parent}{child1} = 'value1';
push @{ $HOH{parent}{child2} }, 'value2';
push @{ $HOH{parent}{child2} }, 'value3';
###
output:
{
parent => {
child1 => "value1",
child2 => ["value2", "value3"] },
}
My preference is the Data::Dump module used as below for your hash.
use Data::Dump qw(pp);
say pp(\%HOH);
| [reply] [d/l] [select] |
|
|