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

I am trying to reference two elements in a hash with one key.
e.g. select value[0], value[1], value[1]} from table. I want value[0] to be the key that refers to value[1] or value[2] Here is what I tried while ($values = fetchrow_array()){ my $hash = ($value[0] => $value[1]); push (@{$hash{$values[0]}}, values[2]) } foreach $value (keys %has){ print "$hash: @($hash{$value}\n"; }
this is the error I recieve
Can't use string ("861") as an ARRAY ref while "strict refs" in use

Replies are listed 'Best First'.
Re: 2 elements referenced by one Key
by dragonchild (Archbishop) on Feb 21, 2005 at 16:29 UTC

    First off, kudos for using strict. That saved you from serious issues.

    my $hash = { $value[0] => [ $value[1], $value[2] ], };

    Being right, does not endow the right to be rude; politeness costs nothing.
    Being unknowing, is not the same as being stupid.
    Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence.
    Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.

Re: 2 elements referenced by one Key
by Fendaria (Beadle) on Feb 21, 2005 at 16:56 UTC

    Not 100% sure which way you are trying to go.

    If you want multiple keys to one hash value take a look at the CPAN module Tie::Aliashash. It lets you do

    $hash{ 'foo', 'bar' } = 'baz';

    If you want multiple values per key take a look at the CPAN module Tie::Hash::Multivalue. It lets you do

    $hash->{'sample'} = 'one'; $hash->{'sample'} = 'two'; # $hash->{'sample'} now contains ['one','two']
    among other things.

Re: 2 elements referenced by one Key
by Tanktalus (Canon) on Feb 21, 2005 at 16:33 UTC

    Two ways off the top of my head:

    # method 1 - always use an array: while (my @values = fetchrow_array()){ my $hash = ($values[0] => [ $values[1] ]); push (@{$hash{$values[0]}}, values[2]) }
    or ...
    # method 2 - switch scalars to arrays dynamically (good for other # cases, not so good for yours, here for completeness only) # rather than a simple push: if (exists $hash{$values[0]}) { if (not ref $hash{$values[0]} or ref $hash{$values[0]} ne 'ARRAY') { $hash{$values[0]} = [ $hash{$values[0]} ]; } push @{$hash{$values[0]}}, $hash{$values[2]};
    I use the latter in more general cases where I want to default to a single scalar for most cases, and only fall back to arrays when I get the duplication. But the first one makes more sense in the code snippet you gave.

    Update: Off-by-everything error in the inner if in method 2, noted by jdalbec. Replaced "eq" with "ne". (Off-by-everything errors are more common for me than off-by-one errors :->)

Re: 2 elements referenced by one Key
by jdalbec (Deacon) on Feb 21, 2005 at 16:43 UTC
    Good to see that you're using strict. If you change line 2 to
    my %hash = ($values[0] => [$values[1]]);
    then the warning will go away. However, you still have a problem because %hash is local to the while() loop. When you get to the foreach loop it will have gone out of scope and you won't get any output. Try this instead:
    my %hash; while ($values = fetchrow_array()){ push (@{$hash{$values[0]}}, values[1]); push (@{$hash{$values[0]}}, values[2]); } foreach $value (keys %hash){ print "\$hash: @{$hash{$value}}\n"; }
    You may wonder how it's possible to use an undefined value as an array reference. This is a bit of Perl magic called autovivification.