Reputation: 2715
I am currently trying to pass a 32 by 48 matrix file to a multi-dimensional array in Perl. I am able to access all of the values, but I am having issues accessing a specific value.
Here is a link to the data set: http://paste-it.net/public/x1d5301/
Here is what I have for code right now.
#!/usr/bin/perl
open FILE, "testset.txt" or die $!;
my @lines = <FILE>;
my $size = scalar @lines;
my @matrix = (1 .. 32);
my $i = 0;
my $j = 0;
my @micro;
foreach ($matrix)
{
foreach ($lines)
{
push @{$micro[$matrix]}, $lines;
}
}
Upvotes: 2
Views: 10908
Reputation: 20280
I see the question is pretty old, but as the author has just edited the question, perhaps this is still of interest. Also the link to the data is dead, but since other answers use space as the separator, I will too.
This answer demonstrates Tie::Array::CSV
which allows random access to a CSV (or other file parsable with Text::CSV
).
#!/usr/bin/env perl
use strict;
use warnings;
use Tie::Array::CSV;
## put DATA into temporary file
## if not using DATA, put file name in $file
use File::Temp ();
my $file = File::Temp->new();
print $file <DATA>;
##
tie my @data, 'Tie::Array::CSV', $file, {
text_csv => {
sep_char => " ",
},
};
print $data[1][2];
__DATA__
1 2 3 4 5
6 7 8 9 1
2 3 4 5 6
Upvotes: 1
Reputation: 118166
To clarify a tangential point to Axeman's answer:
See perldoc -f split:
A split on
/\s+/
is like asplit(' ')
except that any leading whitespace produces a null first field. A split with no arguments really does asplit(' ', $_)
internally.
#!/usr/bin/perl
use YAML;
$_ = "\t1 2\n3\f4\r5\n";
print Dump { 'split' => [ split ] },
{ "split ' '" => [ split ' ' ] },
{ 'split /\s+/' => [ split /\s+/ ] }
;
Output:
--- split: - 1 - 2 - 3 - 4 - 5 --- split ' ': - 1 - 2 - 3 - 4 - 5 --- split /\s+/: - '' - 1 - 2 - 3 - 4 - 5
Upvotes: 1
Reputation: 29854
It doesn't seem you understand that $matrix
only indicates @matrix
when it is immediately followed by an array indexer: [ $slot ]
. Otherwise, $matrix
is a completely different variable from @matrix
(and both different from %matrix
as well). See perldata.
#!/usr/bin/perl
use English;
Don't! use English--that way!
This brings in $MATCH
, $PREMATCH
, and $POSTMATCH
and incurs the dreaded $&
, $`, $'
penalty. You should wait until you're using an English variable and then just import that.
open FILE, "testset.txt" or die $!;
Two things: 1) use lexical file handles, and 2) use the three-argument open
.
my @lines = <FILE>;
As long as I'm picking: Don't slurp big files. (Not the case here, but it's a good warning.)
my $size = scalar @lines;
my @matrix = (1 .. 32);
my $i = 0;
my $j = 0;
my @micro;
I see we're at the "PROFIT!!" stage here...
foreach ($matrix) {
You don't have a variable $matrix
; you have a variable @matrix
.
foreach ($lines) {
The same thing is true with $lines
.
push @{ $micro[$matrix]}, $lines;
}
}
Rewrite:
use strict;
use warnings;
use English qw<$OS_ERROR>; # $!
open( my $input, '<', 'testset.txt' ) or die $OS_ERROR;
# I'm going to assume space-delimited, since you don't show
my @matrix;
# while ( defined( $_ = <$input> ))...
while ( <$input> ) {
chomp; # strip off the record separator
# Load each slot of @matrix with a reference to an array filled with
# the line split by spaces.
push @matrix, [ split ]; # split = split( ' ', $_ )
}
Upvotes: 6
Reputation: 132920
If you are going to be doing quite a bit of math, you might consider PDL (the Perl Data Language). You can easily set up your matrix and before operations on it:
use 5.010;
use PDL;
use PDL::Matrix;
my @rows;
while( <DATA> ) {
chomp;
my @row = split /\s+/;
push @rows, \@row;
}
my $a = PDL::Matrix->pdl( \@rows );
say "Start ", $a;
$a->index2d( 1, 2 ) .= 999;
say "(1,2) to 999 ", $a;
$a++;
say "Increment all ", $a;
__DATA__
1 2 3
4 5 6
7 8 9
2 3 4
The output shows the matrix evolution:
Start
[
[1 2 3]
[4 5 6]
[7 8 9]
[2 3 4]
]
(1,2) to 999
[
[ 1 2 3]
[ 4 5 999]
[ 7 8 9]
[ 2 3 4]
]
Increment all
[
[ 2 3 4]
[ 5 6 1000]
[ 8 9 10]
[ 3 4 5]
]
There's quite a bit of power to run arbitrary and complex operations on every member of the matrix just like I added 1 to every member. You completely skip the looping acrobatics.
Not only that, PDL does a lot of special stuff to make math really fast and to have a low memory footprint. Some of the stuff you want to do may already be implemented.
Upvotes: 3
Reputation: 74272
You probably need to chomp
the values:
chomp( my @lines = <FILE> );
Upvotes: 2