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

Hi, What I want to do is work out the length of an array which is held inside another array. For example:
@alpha = qw/a b c d/; @beta = qw/e f/; $arr[0] = @alpha; $arr[1] = @beta;
I want to, for example, determine the number of elements in the array $arr[0]. Thanks

Replies are listed 'Best First'.
Re: determining length of multidimensional arrays
by lima1 (Curate) on Apr 01, 2006 at 15:28 UTC
    your code does not work as you might expect. you will get an array qw/4 2/. you have to push a reference in @arr:
    use Data::Dumper; @alpha = qw/a b c d/; @beta = qw/e f/; $arr[0] = \@alpha; $arr[1] = \@beta; print Dumper(@arr); print scalar @{$arr[0]};
Re: determining length of multidimensional arrays
by davido (Cardinal) on Apr 01, 2006 at 16:59 UTC

    You have to pay attention to the sigils to understand why your method isn't working as you hoped. If the variable entity starts with a $ sigil, it's a scalar container. If it starts with a @ sigil, it's an array (a list container). A scalar container cannot hold a list. That means that the following statement behaves as follows:

    $arr[0] = @alpha;

    Behavior: Look at the container on the left hand side of the = operator. It's a scalar. That means that the right-hand side of the statement is evaluated in scalar context. An array, evaluated in scalar context doesn't return its contents, but rather, returns the number of elements it contains.

    What you want, instead, is to put a reference (which is itself a scalar value) to the array into the scalar container '$arr[0]'. You can do that like this:

    $arr[0] = \@alpha;

    That puts a "pointer" or more appropriately described as a "reference" to @alpha into @arr[0]

    In many situations you might prefer to hold a reference to a copy of @alpha's contents instead of a reference to @alpha itself. You can do that like this:

    $arr[0] = [ @alpha ];

    And in the name of not typing $arr[0], $arr[1], $arr[2], and so on, you can also do something a little cunning like this:

    foreach( \@alpha, \@beta ) { push @arr, $_; }

    ...or for a copy instead of a direct reference...

    foreach( [ @alpha ], [ @beta ] ) { push @arr, $_; }

    See perlref, perlreftut, and perllol for a much better explanation than I can give.

    Now to determine length, you can do this:

    my $len = @arr; # Number of lists contained in @arr. my $len = @{ $arr[0] }; # Number of elements contained in the list # referenced by $arr[0].

    The idea is to evaluate the array, or one of the array refs held in the array, in scalar context. Doing so will tell you how many elements that level contains.


    Dave

Re: determining length of multidimensional arrays
by Ido (Hermit) on Apr 01, 2006 at 15:35 UTC
    Please read perlreftut.
    Please also notice that you can't simply get a list into a scalar, and when you evaluate an array in scalar context, you get its size.
Re: determining length of multidimensional arrays
by TedPride (Priest) on Apr 02, 2006 at 00:38 UTC
    Or you can just access the length of the array directly instead of forcing it with scalar context, though this admittedly does return n - 1 instead of n, due to Perlish oddness.
    my @arr = (0,1,2); my @nested = (3,4,\@arr); print $#{$nested[2]};

      Or also due to the same Perl oddness OP could:

      my @arr = (0,1,2); my @nested = (3,4,\@arr); print scalar @{$nested[2]};

      Prints:

      3

      DWIM is Perl's answer to Gödel