Home > Net >  Why can't I push items into a hash of arrays, in Perl?
Why can't I push items into a hash of arrays, in Perl?

Time:09-17

What I want here is for @{$allHash{$key1}} to be ["item1", "item2"].

Pushing doesn't work, and all the print statements are to try and find where the pushed items went. Using -> notation in the push is even worse, it makes $temp[0][0] and line 24 show an array instead of the item.

    #use strict;   # I've turned these off here to make the code easier to read
    #use warnings;

    my %allHash = ();
    my $key1 = "key1";
    my $item1 = "item1";
    my $item2 = "item2";
    #if (!exists($allHash{key1})) {$allHash{key1}=();}; # makes no difference, the array autovivefies anyway

    push (@{$allHash{$key1}},  $item1);         # push 1st item
    print"\n\nat11: pushed $key1, $item1";
    my @temp = $allHash{$key1};
    print"\nat13:temp=@temp, length=",0 @temp, ", temp[0]=$temp[0], temp[0][0]=$temp[0][0]";
    print"\nat14: allHash{$key1}[0]= $allHash{$key1}[0]";
    print"\nat15: allHash{$key1}[1]= $allHash{$key1}[1]";
    print"\nat16: allHash{$key1}[0][0]= $allHash{$key1}[0][0]";
    print"\nat17: allHash{$key1}[1][0]= $allHash{$key1}[1][0]";
    print"\nat18: allHash{$key1}[0][1]= $allHash{$key1}[0][1]\n";
    print"\n----------------";
    
    push (@{$allHash{$key1}},  $item2);         # push 2d item
    print"\n\nat21: pushed $key1, $item2";
    @temp = @{allHash{$key1}};
    print"\nat23:temp=@temp, length=",0 @temp, ", temp[0]=$temp[0], temp[0][0] =$temp[0][0]";
    print"\nat24: allHash{$key1}[0]= $allHash{$key1}[0]";
    print"\nat25: allHash{$key1}[1]= $allHash{$key1}[1], allHash{$key1}[1][0] =$allHash{$key1}[1][0]";
    print"\nat26: allHash{$key1}[0][0]= $allHash{$key1}[0][0]";
    print"\nat27: allHash{$key1}[1][0]= $allHash{$key1}[1][0]";
    print"\nat28: allHash{$key1}[0][1]= $allHash{$key1}[0][1]\n";

The output from the above program is:

at11: pushed key1, item1
at13:temp=, length=1, temp[0]=ARRAY(0x331eb8), temp[0][0]=item1
at14: allHash{key1}[0]=item1
at15: allHash{key1}[1]=
at16: allHash{key1}[0][0]=
at17: allHash{key1}[1][0]=
at18: allHash{key1}[0][1]=

----------------

at21: pushed key1, item2
at23:temp=ARRAY(0x331ee8), length=1, temp[0]=ARRAY(0x331ee8), temp[0][0]=item1
at24: allHash{key1}[0]=item1
at25: allHash{key1}[1]= ARRAY(0x332020), allHash{key1}[1][0]=
at26: allHash{key1}[0][0]=
at27: allHash{key1}[1][0]=
at28: allHash{key1}[0][1]=

What's bizarre is that this almost identical code from another of my programs works perfectly.

%hedgeHash = ();    # collect the members of each hedge as an array, using stub as key
for (my $i=0; $i<@options; $i  )
{   $Hstub = $options[$i][$iStub];
    push @{$hedgeHash{$Hstub}}, $i; # hedgehash should contain array of members of the hedge.
}

What's even more bizarre is that if I remove the parentheses from the push statement, I no longer get 'item1' as the output of @temp and on lines 14 and 24, but get another array! WTF??

CodePudding user response:

Please see a sample code bellow demonstrating a use of hash of arrays.

Indeed OP's coding style makes code reading somewhat difficult.

use strict;
use warnings;
use feature 'say';

use Data::Dumper;

my %allHash;
my $key1 = 'key1';
my $item1 = 'item1';
my $item2 = 'item2';
my $item3 = 'item3';
my $item4 = 'item4';
my $item5 = 'item5';

push @{$allHash{$key1}}, $item1;
push @{$allHash{$key1}}, $item2;

$allHash{$key1}[2] = $item3;
$allHash{$key1}[3] = [$item4,$item5];

say Dumper(\%allHash);

Output

$VAR1 = {
          'key1' => [
                      'item1',
                      'item2',
                      'item3',
                      [
                        'item4',
                        'item5'
                      ]
                    ]
        };
  • Related