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

Say i have a file with a matrix whose dimensions i dont know and i need to read it in, how would you make a program as short as possible, that can read in any matrix with any dimensions?? I did something similar but its not flexible :/ thanks

Replies are listed 'Best First'.
Re: how do i read in ANY 2d array
by BrowserUk (Patriarch) on Jul 26, 2011 at 16:23 UTC

    It depends entirely upon how the data is stored in the file.

    For a matrix stored such that the rows are white-space delimited, and columns newline delimited, then this does the trick:

    my @matrix = map[ split ], <$filehandle>;

    Though if the file/matrix is of any substantial size, then this may be preferable:

    my @matrix; push @matrix, [ split ] while <$filehandle>;

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: how do i read in ANY 2d array
by davido (Cardinal) on Jul 26, 2011 at 18:45 UTC

    The following operates under the assumption that all rows in your matrix will have equal length (or that you don't care if they don't). Another assumption is that each row of the file corresponds to a row of the matrix. Also, it's expecting comma delimited fields with no embedded (significant) commas. That could be something like a numeric matrix. If you want space delimited with no embedded (significant) space you would change the split to [ split ]

    my @matrix; while( <> ) { chomp; push @matrix, [ split /\s*,\s*/, $_ ]; } # Now @matrix is an array of array references.

    You asked to make it as short as possible. Using map shortens the construct:

    my @matrix = map { chomp; [ split /\s*,\s*/, $_ ] } <>;

    That's shortens it while avoiding a negative impact on readability. It does have the disadvantage of slurping the file, but unless your matrix is really big that ought not matter. I don't think you're looking for a golf solution, so it makes sense to stop there, and in fact, recommend the while(){} method instead.

    Update: Bah! I should have read that BrowserUk already provided a similar and perfectly good answer. Well, at least now you get two explanations of the same concepts.


    Dave

Re: how do i read in ANY 2d array
by fisher (Priest) on Jul 26, 2011 at 15:41 UTC
    2d array with any dimensions

    Excuse me? What do you mean by that?

      like a matrix with any dimensions, like 5by5 orr 4by 6 or 2by3
        Учи матчасть ("learn your equipment", jokingly).

        '2d' means 'two dimensions', like matrix N x M, for any N and M; thus, matrix 5by5 and 4by6 both are 2d arrays (square matrices). Adding third dimension makes N x M x L (cubic matrix), fourth - N x M x L x K (4d matrix) and so on.

Re: how do i read in ANY 2d array
by Marshall (Canon) on Jul 27, 2011 at 13:42 UTC
    We've seen this question before. I answered at Re: How to make this code more flexible and actually showed how to make an ArrayOfArray a 2D structure and another type of structure a HashOfArray which used a letter for the row names because you had used that in another question. Arbitrary 2D, 5x5 6x9, 2x7 whatever you want, the code will do it. What didn't you understand about it?

    Update: To boil it down as short as possible, this code will build a 2D array of whatever data is in the DATA segment.

    #!/user/bin/perl -w use strict; use Data::Dump qw(pp); my @AoA; push @AoA, [split] while (<DATA>); print pp(\@AoA); __DATA__ 11 12 13 14 15 16 17 21 22 23 24 25 26 27 31 32 33 34 35 36 37 41 42 43 44 45 46 47 51 52 53 54 55 56 57