I've got a hash of arrays that's declared as follows:
my %hash;
push @{ $hash{ $value1[$_] } }, [ $value1[$_], $value2[$_], $value3[$_], $value4[$_], $value5[$_] ] for 0 .. $#value1;
I want to be able to inspect the values for each key using:
open KEYS, '>keys.txt' or die "Can't write to 'keys.txt'\n";
for my $key ( sort keys %hash ) {
print KEYS "Key: $key contains the values: ";
for my $value ( @{$hash{$value1}} ) {
print KEYS "$value ";
}
print KEYS "\n";
}
close(KEYS);
While I can visualise the keys and associated values using Data::Dumper, the output from the above code gives memory locations, rather than values, for each key. E.g:
Key: 'Value1' contains the values: ARRAY(0x7fcd8645ba68)
Even though I'm pushing the same number of values onto each array, each key contains different numbers of values
Is there something wrong with the way I'm going about this?
First, in your inner loop, you have
for my $value ( @{$hash{$value1}} ) {
print KEYS "$value ";
}
What on earth is $value1
? I think you wanted to use $key
. Always use strict; use warnings
to get warned about undefined values and undeclared variables.
Next, let's take a look what happens when we do
my %hash;
push @{ $hash{ $value1[$_] } }, "(value$_)" for 0 .. $#value1;
instead, i.e. we just push a string onto the arrayref in the hash. Then, the output looks somewhat like
Key: Value1 contains the values: (value0)
Key: Value2 contains the values: (value1)
Key: Value3 contains the values: (value2)
Aha! Whatever we push onto that arrayref is printed out as is. If you push an anonymous arrayref like [...]
, you get the stringification of that reference: ARRAY(0x1234567)
.
You probably want the contents of that arrayref. Easy: just dereference it.
...;
print KEYS "[@$value] ";
or something like that. The "[...]"
are used here just to visually group the output.
Style notes:
Please consider 3-arg open
with lexical filehandles:
my $filename = "keys.txt";
open my $keys, "<", $filename or die "Can't open $filename: $!";
or use automatic error handling:
use autodie;
open my $keys, "<", "keys.txt";
Either way, it is usually important that you include the reason for the failure $!
in the error message, or it is almost useless.
Instead of using loop, your code may be more elegant with map
and join
, depending on your taste. I would have probably written the loop as
use feature 'say';
for my $key ( sort keys %hash ) {
say {$keys} "Key: $key contains the values: "
. join " ", map { "[@$_]" } @{ $hash{$key} };
}
That's because you're pushing an arrayref instead of a list of values.
Compare
push @array, [ $foo ];
to
push @array, $foo;
Both @array
s contain a single element, but the former holds an arrayref containing $foo
, whereas the latter holds just $foo
.
If you lose the square braces after the first push
argument you'll be good to go.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With