Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot

Undefined Array Reference

by Anonymous Monk
on Apr 22, 2009 at 23:07 UTC ( #759433=perlquestion: print w/replies, xml ) Need Help??
Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Monks, hi there!

I followed a node here while ago and one part of the code got me going, I wish someone could show me a better way to accomplish this issue, I can't figure it out. Is got to be a better and simpler way to do this.
It needs to place a space in the $ref_b to make sure consistency when generating a report out of this and avoid errors.

use strict; use warnings; use Data::Dumper; my $ref_a = [ [ qw/a b c/ ], [ qw/d e f/ ], [ qw/g h i/ ], [ qw/x y z/ ], [ qw/3 4 5/ ], [ qw/6 7 9/ ], ]; my $ref_b = [ [ qw/j k l/ ], [ qw/m n o/ ], [ qw/p q r/ ], ]; for my $i (0..$#$ref_a) { push @{$ref_a->[$i]}, @{$ref_b->[$i]}; } print Dumper($ref_a);

Replies are listed 'Best First'.
Re: Undefined Array Reference
by Nkuvu (Priest) on Apr 22, 2009 at 23:40 UTC

    It took me a minute or three to figure out what the problem was. Correct me if I'm wrong: When you run the code, you get a "Can't use an undefined value as an ARRAY reference at line 21" error and you aren't sure why.

    I can answer that part -- but what I can't answer is exactly what you're trying to do. The for loop is iterating from 0 to the maximum index in $ref_a. That reference is larger than what you'll find in $ref_b. Some simple print statement debugging will help show what I mean:

    print "ref_a: ", $#$ref_a, "\nref_b: ", $#$ref_b, "\n"; for my $i (0..$#$ref_a) { print "Reading element $i\n"; push @{$ref_a->[$i]}, @{$ref_b->[$i]}; }

    With some output:

    ref_a: 5 ref_b: 2 Reading element 0 Reading element 1 Reading element 2 Reading element 3 Can't use an undefined value as an ARRAY reference at li +ne 23

    To correct this problem, you can just choose the minimum of the two ref_a/b indices. But since I don't know what your goal is, I don't know if this will correct your issue.

      The reason for that is a query result from a database, each array ref, since I can not join these tables, are each from these tables, and I don't know how many records each one will be returning, that is the reason for this sample code.
        I'd really like to know why you can't join the tables...
Re: Undefined Array Reference
by almut (Canon) on Apr 22, 2009 at 23:58 UTC

    Maybe something like this?

    ... for my $i (0..$#$ref_a) { push @{$ref_a->[$i]}, @{ ref($ref_b->[$i]) eq 'ARRAY' ? $ref_b->[$i] : [(' ') x 3] }; } print Dumper($ref_a); __END__ $VAR1 = [ [ 'a', 'b', 'c', 'j', 'k', 'l' ], [ 'd', 'e', 'f', 'm', 'n', 'o' ], [ 'g', 'h', 'i', 'p', 'q', 'r' ], [ 'x', 'y', 'z', ' ', ' ', ' ' ], [ '3', '4', '5', ' ', ' ', ' ' ], [ '6', '7', '9', ' ', ' ', ' ' ] ];

    ... my interpretation of the "space in the $ref_b"  :)

      Another interpretation would be "when ref_b runs out of data, don't do anything more to ref_a".

      If this is what's needed then:

      for my $i (0..$#$ref_a) { push @{$ref_a->[$i]}, @{$ref_b->[$i] || []}; }
      Ie, if @{$ref_b} hasn't got as many members as @{$ref_a}, then at some point $ref_b->[$i] is undef, so dereference a reference to an empty array in that case.

      (I also tried to use || last there (ie exit the loop early) but that comes up with a "bizarre" error message.)

      If it's also possible for ref_b to have more members than ref_a, and the extras should be tacked on verbatim, then the range of the for loop needs to be adjusted to cover them. Here's one option which is moderately readable:

      for my $i (0.. ($#$ref_a > $#$ref_b ? $#$ref_a : $#$ref_b) ) {
      Handily, extra elements appear in ref_a automatically as needed, so there's no need for a || [] on the first argument to push.

      Update: Re-reading the thread made me realise that because of the autovivification in ref_a, ikegami's suggestion does acheive all this (I think) but much more subtly. Too subtle for me the first time round ;-)

      use JAPH;
      print JAPH::asString();

Re: Undefined Array Reference
by syphilis (Chancellor) on Apr 22, 2009 at 23:42 UTC
    In your for loop, $ref_b->[$i] doesn't exist for $i greater than 2. Consequently, as soon as $i == 3, you get the error you see.

    What do you want to push onto @{$ref_a->[$i]} when $i is 3, 4 or 5 ?

      Maybe nothing?
      | v for my $i (0..$#$ref_b) { push @{$ref_a->[$i]}, @{$ref_b->[$i]}; }
Re: Undefined Array Reference
by lostjimmy (Chaplain) on Apr 23, 2009 at 13:00 UTC
Re: Undefined Array Reference
by bichonfrise74 (Vicar) on Apr 23, 2009 at 01:27 UTC
    Because the number of elements for each array references are not the same which is why you are getting the error.
Re: Undefined Array Reference
by Marshall (Abbot) on Apr 25, 2009 at 11:05 UTC
    Since your code doesn't produce a result and you haven't told us what you want, this is a guessing game.

    On style, this: for my $i (0..$#$ref_a) is a super red flag. This sort of loop variable is a "non-Perl" way to do things and $# is deprecated anyway.

    I guessed that you wanted to merge the $ref_b stuff into the $ref_a stuff and get a revised version of $ref_a reflecting a new sorted version of those updates (eg "j,k,l" should come before "x,y,z"),like this:

    3 4 5 6 7 9 a b c d e f g h i j k l m n o p q r x y z

    The code below shows how to do that..and what to do if you want numbers to appear after letters (sort order change)...

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://759433]
Approved by ikegami
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (10)
As of 2018-03-17 19:22 GMT
Find Nodes?
    Voting Booth?
    When I think of a mole I think of:

    Results (225 votes). Check out past polls.