Pushing onto / autovivfying array within a hash

Discussion in 'Perl Misc' started by niall.macpherson@ntlworld.com, Mar 15, 2006.

  1. Guest

    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
     
    , Mar 15, 2006
    #1
    1. Advertising

  2. wrote in news:1142419248.717358.291990
    @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. Sinan Unur <>
    (remove .invalid and reverse each component for email address)

    comp.lang.perl.misc guidelines on the WWW:
    http://mail.augustmail.com/~tadmc/clpmisc/clpmisc_guidelines.html
     
    A. Sinan Unur, Mar 15, 2006
    #2
    1. Advertising

  3. wrote in news:1142419248.717358.291990
    @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
    --
    A. Sinan Unur <>
    (remove .invalid and reverse each component for email address)

    comp.lang.perl.misc guidelines on the WWW:
    http://mail.augustmail.com/~tadmc/clpmisc/clpmisc_guidelines.html
     
    A. Sinan Unur, Mar 15, 2006
    #3
  4. Guest

    Re: Pushing onto / autovivfying array within a hash

    A. Sinan Unur wrote:


    >
    > > print Dumper $testhash;

    >
    > 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.
     
    , Mar 15, 2006
    #4
  5. <> wrote:

    > 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?


    --
    Tad McClellan SGML consulting
    Perl programming
    Fort Worth, Texas
     
    Tad McClellan, Mar 15, 2006
    #5
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Dave
    Replies:
    2
    Views:
    428
    Jim Langston
    Aug 15, 2007
  2. rp
    Replies:
    1
    Views:
    594
    red floyd
    Nov 10, 2011
  3. eagle eyes joe
    Replies:
    3
    Views:
    108
    Florian Gross
    Sep 28, 2004
  4. Srijayanth Sridhar
    Replies:
    19
    Views:
    674
    David A. Black
    Jul 2, 2008
  5. Replies:
    4
    Views:
    120
    Mumia W. (on aioe)
    Dec 31, 2006
Loading...

Share This Page