simple matrix
steverippl
created: 2006-05-03 22:59:57
Hi, I've got a number of attributes to store for each user, so I want a matrix to hold this rather than x parallel arrays. I'm trying just to simulate a simple matrix as follows
 
#! /usr/bin/perl

$a = 1; $b = 2; $c = 3;
$d = 4; $e = 5; $f = 6;
$g = 7; $h = 8; $i = 9;

@row = ();
@matrix=();
push (@row, $a);
push (@row, $b);
push (@row, $c);

print "@row\n";

push(@{$matrix}, \@row);

@row = ();
push (@row, $d);
push (@row, $e);
push (@row, $f);

print "@row\n";

push(@{$matrix}, \@row);

@row = ();
push (@row, $g);
push (@row, $h);
push (@row, $i);

print "@row\n";

push(@{$matrix}, \@row);

print "$$matrix[0][0] \n";
You get the idea... why am I getting 7 at the end instead of 1. I mean, I must be over-writing each line or something, but I don't know what!
Re: simple matrix
created: 2006-05-03 23:06:50

Is matrix a reference to an array (@{$matrix}) or an array (@matrix). You've used both. use strict is your friend. It would have caught that error.

Also, you're always pushing a reference to the same variable (@row) over and over again. All rows of your matrix are going to be the same. The following creates multiple row variables (all named @row). The alternative would be to copy @row into a newly create anon aray by replacing \@row with [ @row ].

#! /usr/bin/perl

use strict;
use warnings;

use Data::Dumper;

my $a = 1; my $b = 2; my $c = 3;  # It's bad to use $a and $b
my $d = 4; my $e = 5; my $f = 6;
my $g = 7; my $h = 8; my $i = 9;

my @matrix;

{
   my @row;
   push(@row, $a);
   push(@row, $b);
   push(@row, $c);
   print "@row\n";
   push(@matrix, \@row);
}

{
   my @row;
   push(@row, $d);
   push(@row, $e);
   push(@row, $f);
   print "@row\n";
   push(@matrix, \@row);
}


{
   my @row;
   push(@row, $g);
   push(@row, $h);
   push(@row, $i);
   print "@row\n";
   push(@matrix, \@row);
}

print(Dumper(\@matrix));

or

my @matrix = (
   [ 1, 2, 3 ],
   [ 4, 5, 6 ],
   [ 7, 8, 9 ],
);
Re: simple matrix
created: 2006-05-03 23:13:23

You would be much better using a hash:

use strict;
use warnings;
use Data::Dump::Streamer;

my %users;

while () {
    chomp;
    my ($user, @attributes) = split /\s*,\s*/;
    
    $users{$user} = [@attributes];
}

print $_, " @{$users{$_}}\n" for keys %users;

__DATA__
Fred, 17, male, Perl monk
Joe, 23, male, Perl Monk
Jane, 22, female, Java junkie

Prints:

Jane 22 female Java junkie
Joe 23 male Perl Monk
Fred 17 male Perl monk

DWIM is Perl's answer to Gödel
Re: simple matrix
created: 2006-05-03 23:29:54
And you would be well advised to spend some time becoming acquainted with the "Perl Data Structures Cookbook", found in your documentation as "perldsc".

You might also be well advised to consider using an HoH - a Hash of Hashes which means you do not need to fill every position in the matrix. Whilst in other languages you might find a matrix the easiest way of dealing with such a dataset it has been my experience that in Perl it is rarely the best way. Matrices are best kept for dealing with data which can be represented no other way.

I would also re-iterate the advice already given that you should always use strict and warnings, you would have found the error long before opening your browser to come here.

jdtoronto

Re: simple matrix
created: 2006-05-04 00:10:28

Hi [steverippl], Try this another way,

TIMTOWDI

use strict;
use warnings;
use Array::Reform;
    
my $a = 1; my $b = 2; my $c = 3;
my $d = 4; my $e = 5; my $f = 6;
my $g = 7; my $h = 8; my $i = 9;

my @matrix;

push(@matrix, $a);
push(@matrix, $b);
push(@matrix, $c);
push(@matrix, $d);
push(@matrix, $e);
push(@matrix, $f);
push(@matrix, $g);
push(@matrix, $h);
push(@matrix, $i);

my $rowsize = 3; ####Number of rows
  
for my $row (Array::Reform->reform( $rowsize, \@matrix )){
	$,=" ";
	print @{$row}, "\n";
}

__END__
1 2 3
4 5 6
7 8 9

[GrandFather] done well.

Updated: instead of pushing value into an array in line by line. Use looping,

push(@matrix, $_) foreach($a, $b, $c, $d, $e, $f, $g, $h, $i);

Regards,
Velusamy R.


eval"print uc\"\\c$_\""for split'','j)@,/6%@0%2,`e@3!-9v2)/@|6%,53!-9@2~j';

Re: simple matrix
created: 2006-05-04 09:20:01
gotta add the caveat about $a and $b -- i know this is example code, but don't use those variable names .. they are special global variables for [perldoc://sort]

Can't tell if you really need hardcoded values or if you just flattened it for an example, but if the former you can just do (this should also help visualize the data structure):
use strict;
use warnings;
my @matrix = (
  [ 1, 2, 3 ],
  [ 4, 5, 6 ],
  [ 7, 8, 9 ],
);
use Data::Dumper;
print Dumper \@matrix;
print $matrix[1]->[2] . "\n";  # prints "6"
Re: simple matrix
created: 2006-05-04 11:28:32
Thanks to all of you. Appologies for the sloppy coding, I thought I was saving time in trying to do this little test, but obviously that doesn't pay!! I needed to keep using @row to add to the array because this will happen in a loop, so as long as variables are local and I contain it in {} it works - great! The hash of arrays is probably my best bet as all users have unique usrName.
Re^2: simple matrix
created: 2006-05-04 12:40:20

Here's an updated solution given the new context.

Doesn't work:

for (...) {
   @row = ();
   ...
   push(@maxtrix, \@row);
}

Works:

for (...) {
   my @row;
   ...
   push(@maxtrix, \@row);
}

In the first, each row of the matrix is a reference to the same array (@main::row).
In the second, a new lexical is created every time through the loop, so each row of the matrix is a reference to a different array.

For example,

use Data::Dumper qw( Dumper );

my $pos = tell(DATA);

{
   my @matrix;

   while () {
      chomp;
      @row = split(/:/, $_);
      push(@matrix, \@row);
   }

   print(Dumper(\@matrix));

   # $VAR1 = [
   #           [
   #             'kaijugal',
   #             '789',
   #             'ghi'
   #           ],
   #           $VAR1->[0],
   #           $VAR1->[0]
   #         ];
}

seek(DATA, $pos, 0);

{
   my @matrix;

   while () {
      chomp;
      my @row = split(/:/, $_);
      push(@matrix, \@row);
   }

   print(Dumper(\@matrix));

   # $VAR1 = [
   #           [
   #             'ikegami',
   #             '123',
   #             'abc'
   #           ],
   #           [
   #             'steverippl',
   #             '456',
   #             'def'
   #           ],
   #           [
   #             'kaijugal',
   #             '789',
   #             'ghi'
   #           ]
   #         ];
}

__DATA__
ikegami:123:abc
steverippl:456:def
kaijugal:789:ghi

perlmonks.org content © perlmonks.org and davidrw, GrandFather, ikegami, jdtoronto, Samy_rio, steverippl

prlmnks.org © 2006 edmund von der burg (eccles & toad)

v 0.03