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

Hello dear Monks.
I am currently reworking one of my classes and looked for a better data format.
The whole data is a matrix, but I need no mathematical functions. I know the number of rows in my matrix, yet the number of columns is unknown.
I either have to insert a new entry in an existing column or create a new column.
Using an array of array references does the job but is complicated, I wonder if there is anything in CPAN capable of this which I have not noticed yet or if there is some other more elegant way to approach this data structure I am not aware of.
Thanks.
  • Comment on Resizable Matrix, or similar data structure.

Replies are listed 'Best First'.
Re: Resizable Matrix, or similar data structure.
by jeffa (Bishop) on Jun 02, 2004 at 11:32 UTC

    Actually, i think that using an array of array references is a wonderful fit for this problem. You just need to familiarize yourself with how Perl dereferences them:

    my $two_d = [ [1,2,3], [4,5,6], [7,8,9], ]; # how many columns? print scalar @$two_d; # how many rows in second column? print scalar @{ $two_d->[1] };
    But, having said that, whenever i need a "real" Matrix, i use Math::Matrix. Wonderful module. :) And, it too uses an array reference of array references to store the matrix in:
    use Math::Matrix; use Data::Dumper; my $two_d = [ [1,2,3], [4,5,6], [7,8,9], ]; my $m = Math::Matrix->new($two_d); print Dumper $m;
    but the benefits of using the module instead of rolling your own are the helper methods such as size() and transpose().

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
Re: Resizable Matrix, or similar data structure.
by dragonchild (Archbishop) on Jun 02, 2004 at 11:37 UTC
    Use an Array of Arrays (AoA), definitely. But, flip your thinking. I'm going to assume that you mapped your problem directly to your data structure and set up your outside array as the rows and your inside array as the columns. Flip it.

    Set up the outside array as your columns and the inside array as your rows. Now, creating a new column is simple and adding an entry to an existing column is still easy. Maybe something along the lines of:

    sub new { my $class = shift; my ($max_rows) = @_; my $self = bless { max_rows => $max_rows, data => [], }, $class; } sub add_column { my $self = shift; push @{$self->{data}}, []; } sub add_value { my $self = shift; my ($x, $y, $value) = @_; return unless $x <= $max_rows; return unless $x >= 0; $self->{data}[$y][$x] = $value; } sub get_value { my $self = shift; my ($x, $y) = @_; return $self->{data}[$y][$x]; }

    ------
    We are the carpenters and bricklayers of the Information Age.

    Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose

    I shouldn't have to say this, but any code, unless otherwise stated, is untested

Re: Resizable Matrix, or similar data structure.
by tachyon (Chancellor) on Jun 02, 2004 at 11:39 UTC

    Maybe you want an array(ref) of hash refs so you can use the hash key as the column name? Probably not as memory efficient as an AoA depending on empty columns.

    my $ary = [ { c1 => 1, c3 => 3 }, { c2 => 2, c3 => 3, c4 => 4 }, { c5 => 5 }, ]; my @cols = qw( c1 c2 c3 c4 c5 ); # to set a vaulue in a col that may or may not exist.... $ary->[0]->{c2} = 2; # print out as a table print join " ", @cols, "\n"; for my $ref( @$ary) { print join " ", (map{ defined $ref->{$_}? $ref->{$_} : '~' }@col +s), "\n"; } __DATA__ c1 c2 c3 c4 c5 1 2 3 ~ ~ ~ 2 3 4 ~ ~ ~ ~ ~ 5

    cheers

    tachyon

Re: Resizable Matrix, or similar data structure.
by Hena (Friar) on Jun 02, 2004 at 11:37 UTC
    Don't know how easy. But when doing things with matrices I'd suggest checking out PDL.