Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Oh wise ones,
I'm trying to create a hash of two arrays:
for($i=1;$i<4;$i++) { push(@{$test{obj1}{values}},$i); } for($i=4;$i<7;$i++) { push(@{$test{obj2}{values}},$i); }
Now when I print out the values for both 'obj1' or 'obj2' I get values from both. Am I doing anything wrong? I thought I would only get values contained under the particular one I want
Example output:
foreach $key (keys %test) { foreach $tmpvalue (@{$test{$key}{value}) { print "$key --> $tmpvalue\n"; } } Output: obj1 --> 0 obj1 --> 1 obj1 --> 2 obj1 --> 3 obj1 --> 4 obj1 --> 5 obj1 --> 6 . . .
Thanks, desperate soul

Replies are listed 'Best First'.
Re: Hash of arrays
by Roy Johnson (Monsignor) on Apr 12, 2006 at 17:01 UTC
    Having fixed your syntax error (missing brace) and done what's needed to make it work happily with strict and warnings, it does exactly what you expect:
    use strict; use warnings; my %test; for my $i (1..3) { push(@{$test{obj1}{values}},$i); } for my $i (4..6) { push(@{$test{obj2}{values}},$i); } foreach my $key (keys %test) { foreach my $tmpvalue (@{$test{$key}{values}}) { print "$key --> $tmpvalue\n"; } }

    Caution: Contents may have been coded under pressure.
Re: Hash of arrays
by ikegami (Patriarch) on Apr 12, 2006 at 17:01 UTC

    Did you run your code? It doesn't even compile. And once I fix the compile error by changing
    foreach $tmpvalue (@{$test{$key}{value})
    to
    foreach $tmpvalue (@{$test{$key}{values}})
    it worked as expected.

    obj1 --> 1 obj1 --> 2 obj1 --> 3 obj2 --> 4 obj2 --> 5 obj2 --> 6

    Maybe if you showed us your real code, we could find the error.

    In your real code, either

    • $test{obj1} and $test{obj2} are references to the same hash, or
    • $test{obj1}{values} and $test{obj2}{values} are references to the same array.

    In other words, you have something equivalent to the following in your real code:

    $test{obj1} = \%data; $test{obj2} = \%data; # -or- # # $test{obj1}{values} = \@values; # $test{obj2}{values} = \@values; for($i=1;$i<4;$i++) { push(@{$test{obj1}{values}},$i); } for($i=4;$i<7;$i++) { push(@{$test{obj2}{values}},$i); }
      Sorry, for the bother
      I actually found my bug.
      Thanks for the input though, really appreciate it.
      This was a quick conversion of my original code..