Pushing onto / autovivfying array within a hash

N

niall.macpherson

I have a hash within which I want each element to conatin a reference
to an array . I have checked perldoc perldsc but for some reason cannot
seem to get the syntax for pushing a new element onto the array.

The 'push' line in the code attached fails to compile with 'Global
symbol "$testhash" requires explicit package name at
C:\develop\NiallPerlScripts\clpm10.pl line 34.' and although I have
tried a number of different syntaxes.

Also is there way I can do without the

if(!defined($testhash{$key}{"myarray"}));

line ? I know that if I am assigning a scalar value I can just do

$testhash{$key}{"myscalar"} = 123;

and autovivfication will take care of this but I can't figure out how
to autovivfy a hash element if it contains an array reference.

use strict;
use warnings;
use Data::Dumper;

my %testhash;
while(<DATA>)
{
chomp;
if(/(\d*)\s*(\d*)/)
{
my($key, $val) = ($1, $2);

## Using $testhash{$key}{myarray} = <array>
## rather than $testhash{$key} = <array> since in
## my real world prog there is other stuff in the hash
## in addition to the array which is unique to the key

## Do I need to test this ?
if(!defined($testhash{$key}{"myarray"}))
{
$testhash{$key}{"myarray"} = [$val];
}
else
{
## What is correct syntax here ?? This line won't compile
## From perldoc perldsc
## append new members to an existing family
## push @{ $HoA{"flintstones"} }, "wilma", "betty";
push @{ $testhash{$key}{"myarray"}}, $val;
}
}
}
print Dumper $testhash;
__END__
123 45
456 777
789 999
123 111
123 222
 
A

A. Sinan Unur

(e-mail address removed) wrote in @u72g2000cwu.googlegroups.com:
my %testhash;
while(<DATA>)
{
chomp;
if(/(\d*)\s*(\d*)/)

If you say that nothing can match, than nothing will match.
{
my($key, $val) = ($1, $2);

Both $key and $val are empty strings at some point.
print Dumper $testhash;

This line is the reason you are getting the error, not push.

print Dumper \%testhash;

OTOH:

#!/usr/bin/perl

use strict;
use warnings;
use strict;
use warnings;
use Data::Dumper;

my %hash;
while ( <DATA> ) {
if ( /\A (\d+) \s+ (\d+) \s+ \z /x ) {
my ($key, $val) = ($1, $2);

push @{ $hash{$key}->{myarray} }, $val;
}
}
print Dumper \%hash;
__END__
123 45
456 777
789 999
123 111
123 222
 
A

A. Sinan Unur

(e-mail address removed) wrote in @u72g2000cwu.googlegroups.com:
use strict;
use warnings;

By the way, I wanted to thank you very much for following the posting
guidelines, and thereby making it easy to figure out the problem.

Sinan
 
N

niall.macpherson

A. Sinan Unur wrote:

This line is the reason you are getting the error, not push.

Thanks Sinan - all working now !
while ( <DATA> ) {
if ( /\A (\d+) \s+ (\d+) \s+ \z /x ) {
my ($key, $val) = ($1, $2);

push @{ $hash{$key}->{myarray} }, $val;
}
}

I hadn't actually realised before that \A , \Z and \z could be used as
replacements for '^' and '$' . This is useful to know as I can see
there are certain circs where it will make my code (hopefully) more
readable.
 
T

Tad McClellan

while(<DATA>)
{
chomp;
if(/(\d*)\s*(\d*)/)
{
my($key, $val) = ($1, $2);


If

$_ = 'Hello world!';

your pattern will _match_, and $key/$val will contain empty strings.

That pattern will match *every* string, and so must return
a true value every time, so there isn't much point in
testing it in an if-conditional.

A pattern that matches the empty string is pretty useless.

Maybe you want /(\d+)\s+(\d+)/ instead?

Maybe you want some anchors in the pattern too?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top