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

Dear Perl Monks,
I am using split to parse a string, and have to write an
array from the contents of the string such that every
element of the array is itself a 3x1 array. The code
looks like this:

use strict; use Graph::Matching; use Graph::Matching qw(max_weight_matching); my @sub = []; my @list = split(',', $ARGV[0]); my $n = 0; my @graph = []; my $i = 0; my $j = 0; for ($i=0; $n<my $graph; $i++) { for ($j=0; $j<=2; $j++) { $sub$j = $list$n; $n++; } my $graph$i = @sub; @sub = []; }
It tell me that there is a syntax error in the line
my $graph[$i] = @sub;
Can anyone please, please help with with this?
Thanks very much!

Replies are listed 'Best First'.
Re: Writing an array inside an array
by moritz (Cardinal) on Nov 18, 2010 at 12:51 UTC
    Please read Markup in the Monastery, and put <code>...</code> tags around your code.

    You probably don't want to assing [] to @sub - that way the array doesn't become empty, but holds a single value, which is a reference to an empty array. Use @sub = () instead.

    Also you'll probably want $graph[$i] = \@sub (no my before it. You're assigning to a part of an existing data structure, declaring a new variable doesn't make sense in that context).

    Also please read perllol, which talks about arrays of array references.

      Thank you very much!
      Now, it gives me the error saying
      Global symbol "$graph" requires explicit package name
      in the line
       $graph[$i] = \@sub;
      Can you please help me again?
      Thanks very much!

        try using

        my @graph = ();
        when you initialize the variable at the top of your code. Think of it as a declaration. You should NOT use 'my' again on the variable however.

        HtH

        Misha/Michael - Russian student, grognard, bemused observer of humanity and self professed programmer with delusions of relevance
Re: Writing an array inside an array
by Marshall (Canon) on Nov 18, 2010 at 22:10 UTC
    I am a bit confused as to exactly what you are trying to do, (and things like where $graph comes from), but it appears to me that you are building a 2-D matrix. These are built in Perl the same way that it is done in C except that its a lot easier! Each "row" is a reference to a 1-D array. So this is an "array of array". In this sort of structure everything is a reference until you get to the last dimension.

    The natural thing to do is to use syntax like: $twoDmatrix[$row][$col] to access each element of the matrix.

    I wrote a simple example for you. Below @twoDmatrix is an array which will wind up with references to other arrays. You don't have to know how many "rows" or "columns" that there are going to be in advance, you just start using it and Perl will figure it out! In C you'd have to allocate memory and take care of some other details yourself, but not with Perl.

    Anyway there is no need to make some temporary "sub array" and then stick a reference to it into @twoDmatrix, go ahead and just use the [row][col] coordinate. By the way DO NOT use perl reserved names (like sub) for variable names! Because that creates lots of opportunities for confusion and errors.

    In your main code, I would work with @twoDmatrix instead of using a reference to it because it is easier and takes out one layer of complication. To pass @twoDmatrix to a subrouinte, take a reference to it in the calling line like: graphfunc(\@twoDmatrix); Note that this is how @twoDmatrix is passed to Dumper below - a very handy function for printing data structures while you are debugging. As you can see @twoDmatrix is indeed an AoA (array of array).

    Update:
    Updated code to show how to send a "row" into a sub, remember that @twoDmatrix is an array of references to arrays. So just: somefunc ($twoDmatrix[1]);sends a reference to row 1 into somefunc (see how I called Dumper below). I guess while I'm at it, I should mention that the matrix does not have to be square or even have the same number of columns in each row, however I would guess that in your case, each row will have same number of columns although maybe rows!=columns, which is just fine.

    #!/usr/bin/perl -w use strict; use Data::Dumper; my @list = (7,15,2); my @twoDmatrix =(); # the = () not really needed here. # take off "my" if you want to "clear" the matrix # later at some point, just: @twoDmatrix = (); my $rows = @list; # evaluation of @list in scalar context # yields 3, the number of elements # just replicated @list into multiple rows with # simple offset to make each row different # result is square matrix (num rows = num cols) my ($row, $col); for ($row=0; $row<$rows; $row++) { for ($col=0; $col<@list; $col++) { $twoDmatrix[$row][$col] = $list[$col]+ $row+1; } } print Dumper \@twoDmatrix; print "element [1][2] is $twoDmatrix[1][2] \n"; print Dumper $twoDmatrix[1]; #twoDmatrix[1] is #already a reference! no \ needed. __END__ $VAR1 = [ [ 8, 16, 3 ], [ 9, 17, 4 ], [ 10, 18, 5 ] ]; element [1][2] is 4 $VAR1 = [ 9, 17, 4 ];