perl

getting a 2d array in perl from input


I want to get a 2d array from input in Perl. I will get 2 inputs for number of rows and column of the matrix and get the input in 2 for loops

First I get two variables named $row and $column from input.

Now what I used to do in python was I made 2 for loops and input like this:

matrix = []
for i in range (row):
    temp = []
    for j in range (column):
        x <- input()
        temp.append(x)
    matrix.append(temp)

And now in matrix I have the matrix user has inputted.

In Perl though I can't do the same thing.

this is my code:

print("enter number of rows: ");
chomp(my $row = <>);
print("enter number of columns: ");
chomp(my $column = <>);
my @matrix = ();
for (my $r=0; $r<$row; $r=$r+1){
    my @list = [];
    for(my $c=0; $c<$column; $c=$c+1){
        print("input:\n");
        chomp(my $input = <>);
        push(@list, $input);
    }
    print("list now @list\n");
    push(@matrix, @list);
}

print("final matrix @matrix\n");
print("$matrix[0][0]\n");

This is the output I get after the line print("final matrix @matrix\n"); executes:

final matrix ARRAY(0xddb038) 1 2 ARRAY(0xddb068) 3 4
and after the last print i get this:
Use of uninitialized value in concatenation (.) or string at test.pl line 94, <> line 6.

(btw line 6 is a comment) this is the whole input and output:

enter number of rows: 2
enter number of columns: 2
input:
1
input:
2
list now ARRAY(0xddb038) 1 2
input:
3
input:
4
list now ARRAY(0xddb068) 3 4
final matrix ARRAY(0xddb038) 1 2 ARRAY(0xddb068) 3 4
Use of uninitialized value in concatenation (.) or string at test.pl line 94, <> line 6.

So basically I want the user to input 2 numbers (n and m) and then input an n*m matrix. I can get the 2 numbers. but when getting the numbers of the matrix, I am doing something wrong in pushing it (appending it) to the main matrix and I think I have not understood the difference of '$' and '@' and also [] and ().


Solution

  • You're mixing two different approaches.

    Working with an array:

    my @list;                    # Create an array.
    push( @list, $input );       # Add to it.
    push( @matrix, \@list );     # Add a reference to it to @matrix.
    

    Working with a reference to an array:

    my $list = [];               # Create an anonymous array
    push( @$list, $input );      # Add to it.
    push( @matrix, $list );      # Add a reference to it to @matrix.
    

    Note that [] returns a reference to the anonymous array it creates, so we store that in a scalar. It also means we need to dereference that scalar to access the array (as see in the middle push of the second snippet).

    Note that arrays can't contain arrays, so we approximate arrays of arrays with arrays of array references. (Like Python, really.) So we need to create a reference (e.g. using \) if we have a named array. (This is the part that's different than Python, since you always have a reference there.)

    I prefer the first approach, but either is fine.


    Tip:

    Arrays already start empty.

    my @matrix = ();
    

    is better written as

    my @matrix;
    

    Tip:

    C-style for loops are extremely dense, hard to read.

    for (my $r=0; $r<$row; $r=$r+1)
    

    is better written as

    for my $r ( 0 .. $r-1 )