Reputation: 647
I'm trying to iterate over a 2D array that is structured in this specific way. Whether or not this is a good way to structure the array is another question - I still need to be able to iterate over it (if it is possible).
@row1 = ( "Current Scan", "Last Month");
@row2 = ( "240", "0");
@row3 = ( "226", "209");
@row4 = ( "215", "207");
@array = (\@row1, \@row2, \@row3, \@row4);
print Dumper(@array);
printarray(@array);
Dumper gives me the following output:
$VAR1 = [
'Current Scan',
'Last Month'
];
$VAR2 = [
'240',
'0'
];
$VAR3 = [
'226',
'209'
];
$VAR4 = [
'215',
'207'
];
I've tried several for loops with no success. Each only prints the first row ($VAR1) and quits. Here is my most recent attempt:
sub printarray {
@array = shift;
$rowi = 0;
foreach my $row (@array) {
for (my $coli = 0; $coli <= @$row; $coli++) {
print "$array[$rowi][$coli]\n";
}
$rowi++;
}
}
I'm obviously overlooking something simple. What am I doing wrong? Thanks in advance!
Upvotes: 1
Views: 2767
Reputation: 98508
Are you looking for something like this:
#!/usr/bin/perl
use warnings;
use strict;
use Algorithm::Loops 'MapCar';
my @row1 = ( "Current Scan", "Last Month");
my @row2 = ( "240", "0");
my @row3 = ( "226", "209");
my @row4 = ( "215", "207");
my @array = (\@row1, \@row2, \@row3, \@row4);
MapCar { print "Scan: $_[0]: $_[1], $_[2], $_[3]\n" } @array;
Upvotes: 0
Reputation: 35828
When you pass the array into the subroutine, you're essentially passing in eight scalars. Then, when you do
sub printarray {
@array = shift;
... you're popping off only the first element in the list. Try:
sub printarray {
@array = @_;
Upvotes: 3
Reputation: 62109
Yes, the problem is in the way you're passing the array to the subroutine. Perl flattens arrays in parameter lists. Basically, printarray(@array)
is (in this example) equivalent to printarray($array[0], $array[1], $array[2], $array[3])
. The shift
at the beginning of printarray
takes the first parameter and assigns it to @array
. So no matter how big the array is, printarray
only sees the first element.
Upvotes: 1
Reputation: 28753
If you want just print the array, try following code:
foreach my $row (@array) {
foreach my $elem (@$row) {
print $elem; ## print elements without separator
}
print "\n"; ## new line after row
}
If you need indexes for some purpose, here we go:
for(my $row_i = 0; $row_i < @array; $row_i++) {
for(my $column_i = 0; $column_i < @{ $array[$row_i] }; $column_i++) {
print $array[$row_i][$column_i];
}
}
The idea is that @array
in scalar context returns number of elements in array. And @{ $array[$row_i] }
is a little more tricky. It dereference array stored in $array[$row_i]
.
Update for subroutine:
In perl you can pass array by reference:
printarray(\@array); ## pass reference
sub printarray {
my $array_ref = shift; ## no copy created
foreach my $row (@$array_ref) { ## now we need to dereference
...
}
}
You can also pass a copy of array:
printarray(@array);
sub printarray {
my @array_copy = @_; ## store local copy of array
...
}
For more details take a look at How can I pass/return a {Function, FileHandle, Array, Hash, Method, Regex}? manual page.
And please add use strict;
at the begining of programm. It'll force you to declare all variables, but will save bunch of time if you type something incorrectly.
Upvotes: 10
Reputation: 1983
#!/usr/bin/perl use warnings; use strict; my @row1 = ( "Current Scan", "Last Month"); my @row2 = ( "240", "0"); my @row3 = ( "226", "209"); my @row4 = ( "215", "207"); my @array = (\@row1, \@row2, \@row3, \@row4); foreach my $row (@array) { foreach my $value (@$row) { print "$value\n"; } }
This will print
Current Scan Last Month 240 0 226 209 215 207
Not sure if that's what you wanted.
Upvotes: 1