Perl Hash of Arrays of Arrays
I'm having some variables in my Hash of multidimensional arrays disappear as soon as I leave a for-loop. The variables are printed correctly one-by-one in the loop, but when I print any item outside of the loop, it is always empty except for the first item.
for my $y (0..$last_row - 2) {
my $mlid = $Sheet->Cells($y+2, 1)->{'Value'};
my @a = ();
$a[0] = $Sheet->Cells($y+2, 3)->{'Value'};
$a[1] = $Sheet->Cells($y+2, 4)->{'Value'};
$a[2] = $Sheet->Cells($y+2, 6)->{'Value'};
$a[3] = $Sheet->Cells($y+2, 7)->{'Value'};
$a[4] = $Sheet->Cells($y+2, 8)->{'Value'};
push @{$longHash{$mlid}}, [ @a ];
print "Item in Array in Hash: $longHash{$mlid}[1][0]\n"; #this prints nothing
if (exists $numPeople{$mlid}){
$numPeople{$mlid}++;
}else{
$numPeople{$mlid} = 0;
$numPeople{$mlid}++;
}
}
print "Item in Array in Hash: $longHash{7202}[0][0]\n"; #this prints properly
print "Item in Array in Hash: $longHash{7202}[1][0]\n"; #this prints nothing
The behavior SHOULD be:
I have a hash. The key for a single mlid gives an array (representing a person). In each of the array, there should be another array, in which the 0-4 indexes are defined from an Excel file I'm reading.
So, to get the data from the mlid 7202, from the 7th person, and the 4t开发者_JAVA百科h column in Excel, I should put $longHash{7202}[7][1] (because I mapped the 4th column to the 1th value of the array.)
You are overwriting $longHash{$mlid}
in every iteration of the loop, so in the best case $longHash{7202}[$x]
will only be defined for one value of $x
.
Unless you are doing something a lot more complicated than what you show here, I don't think you need to clear $longHash{$mlid}
at all. Saying
$longHash{key}[index] = expression
will auto-vivify both $longHash{key}
and $longhash{key}[index]
without the need for any pre-initialization.
( $longHash{$mlid} = ()
also looks a little strange -- you are assigning an empty list to a scalar variable. I don't think it's any different from saying $longHash{$mlid}=0
. If you meant to set it to an empty array reference, then you should use []
instead of ()
).
I see two problems.
$longHash{$mlid} = ()
You are trying to set a scalar field to a list. {$mlid}` should be set to a list ref, not a list. The simplest fix is $longHash{$mlid} = []
, but that won't fix the real issue.
2.
$longHash{$mlid}[$y] = [ @a ];
in combination with $longHash{$mlid} = ();
You are clearing $longHash{$mlid}
on every pass thru the loop, then trying to assign to a non-zero index. Maybe what you want here is a hash of hash rather than a hash of list.
UPDATE
In your new version, I think
push @{$longHash{$mlid}}, [ @a ];
should just be
$longHash{$mlid} = [ @a ];
UPDATE 2
I think your code should be working now.
It seems to be equivalent to my simplified example below:
my %hash;
my @a;
$a[0] = "Fred";
$a[1] = 31;
$a[2] = "Melbourne";
push @{$hash{7202}}, [ @a ];
$a[0] = "Mary";
$a[1] = 25;
$a[2] = "Sydney";
push @{$hash{7202}}, [ @a ];
print $hash{7202}[0][0] . "\n";
print $hash{7202}[1][0] . "\n";
UPDATE 3
Please add
use warnings;
use strict;
to ensure that all the array indexes you think exist do exist.
And try iterating over your data to print it, e.g.
for my $mlid (keys %hash) {
my $recordref = $hash{$mlid};
my @record = @$recordref;
for my $i (0..scalar(@record)-1) {
printf "mlid %s person %d name %s\n", $mlid, $i, $record[$i][0];
}
}
精彩评论