Re: Array of arrays
by tobyink (Canon) on Jul 18, 2013 at 22:15 UTC
|
push( @array_array, @array1, @array2, @array3);
should probably be:
push( @array_array, \@array1, \@array2, \@array3);
And this:
my (@array1, @array2, @array3) = { shift @_ };
should be:
my @array1 = @{ shift(@_) };
my @array2 = @{ shift(@_) };
my @array3 = @{ shift(@_) };
package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name
| [reply] [d/l] [select] |
|
|
I agree with tobyink, except that recreating the arrays when entering the second routine is not really optimal:
sub secondRoutine {
my @array1 = @{ shift(@_) };
my @array2 = @{ shift(@_) };
my @array3 = @{ shift(@_) };
print ("Test first value in array1: $array1[0]");
print ("Test third value in array2: $array2[2]");
print ("Test fifth value in array3: $array3[4]");
}
I would usually prefer something like this:
<c>sub secondRoutine {
my ($array1_ref, $array2_ref, $array3_ref) = @_;
print ("Test first value in array1: $$array1_ref[0]");
print ("Test third value in array2: $$array2_ref[2]");
print ("Test fifth value in array3: $$array3_ref[4]");
}
This is matter open to discussion. Sometimes, I also create intermediary arrays from arrayrefs or hashref to make sure that I am really understanding my complicated data structure, but, here, it seems quite simple, no point of using memory to copy data structures.
Update: fixed the copy-and-paste error seen by Monk::Thomas. | [reply] [d/l] [select] |
|
|
(Copy&Paste error in your 'sub secondRoutine'? You define $array1_ref, $array2_ref, $array3_ref but use $$array1[0])
sub secondRoutine {
# there's nothing wrong here, but $aref (and $href) are shorter and
# convey the same meaning
#my ($array1_ref, $array2_ref, $array3_ref) = @_;
my ($aref1, $aref2, $aref3) = @_;
# - use references directly
# - added newlines for clearer output
# - brackets are unnecessary (just a style choice, no actual impact)
#print ("Test first value in array1: $$array1[0]");
#print ("Test third value in array2: $$array2[2]");
#print ("Test fifth value in array3: $$array3[4]");
print "Test first value in array1: ", $aref1->[0], "\n";
print "Test third value in array2: ", $aref2->[2], "\n";
print "Test fifth value in array3: ", $aref3->[4], "\n";
}
| [reply] [d/l] |
|
|
print ("1st: $array1[0]");
print ("2nd: $array1[1]");
print ("3rd: $array1[2]");
print ("4th: $array1[3]");
print ("5th: $array1[4]");
print ("6th: $array1[5]");
print ("7th: $array1[6]");
print ("8th: $array1[7]");
print ("9th: $array1[8]");
print ("10th: $array1[9]");
print ("11th: $array1[10]");
print ("12th: $array1[11]");
I get the following error:
1st: ARRAY(0x7fd4bb012010)
2nd: ARRAY(0x7fd4bb02f768)
3rd: ARRAY(0x7fd4bb0120a0)
4th: ARRAY(0x7fd4bb012028)
5th: ARRAY(0x7fd4bb012070)
6th: ARRAY(0x7fd4bb02f648)
7th: ARRAY(0x7fd4bb045e80)
8th: ARRAY(0x7fd4bb0462e8)
9th:
10th:
11th:
12th :
Use of uninitialized value $array1[8] in concatenation (.) or string
Use of uninitialized value $array1[9] in concatenation (.) or string
Use of uninitialized value $array1[10] in concatenation (.) or string
Use of uninitialized value $array1[11] in concatenation (.) or string
The strange thing is I have 9 arrays (array1, array2, ..., array9) in my array of arrays. But even when I am only calling array1 (which should have ~200 indices), it seems to be considering each array in the array of arrays as simply an index in the first of its arrays??
| [reply] [d/l] [select] |
|
|
my @first_array = @{$array1[0]};
print @first_array;
Or maybe better, to print all of the arrays:
foreach my $array_ref (@array1) {
print @{$array_ref};
}
The remaining errors for 'Use of uninitialized value' are telling you that those parts of the parent array are not defined, and therefore cannot be printed (you would have to see the internal of perlfunc's print for the explanation behind the concatenation part...).
David
| [reply] [d/l] [select] |
|
|
SuzuBell,
If you are still having problems fixing your data structure to properly print your values out, use Data::Dumper module to see how your data structure is formed. Check what you are printing again and compare it with the previous solutions given.
If you tell me, I'll forget.
If you show me, I'll remember.
if you involve me, I'll understand.
--- Author unknown to me
| [reply] |
|
|
| [reply] |
Re: Array of arrays
by kcott (Archbishop) on Jul 19, 2013 at 13:56 UTC
|
G'day SuzuBell,
Firstly, a few comments on your code (some of which may have already been addressed in other parts of this thread):
-
In general, you should not be prefixing your subroutine calls with an '&'.
In fact, I would go so far as to say don't ever do it unless you know exactly why you're doing it.
See perlsub for details.
-
You should not simply assume that some element of some array contains valid data.
You need to test for this and code appropriate actions (which may include setting a default value or not processing that element).
Not doing this is the likely cause of your "... uninitialised value ..." messages.
-
You appear to have a general lack of knowledge about references.
That's fine: it's just something you need to learn — try the perlreftut tutorial (perlref has more complete details).
-
As you're working with complex data structures, you should look at the Perl Data Structures Cookbook. I'd recommend reading the initial sections up to CODE EXAMPLES; then, as a minimum for your current script, the ARRAYS OF ARRAYS section.
-
You're limiting yourself by hard-coding array variables with numbers: consider the number of lines of code you'd have to change if you needed an @array4.
You can put (anonymous) references to each array into another array which can expand or contract as required.
-
You're doing lots of unnecessary processing with the continual referencing and dereferencing of your arrays.
This will slow down your application and could potentially lead to memory issues.
In the code I've posted below, see how I've eliminated all the additional processing associated with your two subroutine calls: secondRoutine(firstRoutine());
The code below (which includes sample input and output) shows how to create, manipulate and access the type of array data you appear to be working with.
It addresses all the issues I raised. I'll leave you to adapt it to your specific requirements.
$ perl -Mstrict -Mwarnings -le '
use constant MAX_COLUMN_INDEX => 2;
secondRoutine(firstRoutine());
sub firstRoutine{
my $matrix;
while (<>) {
my @fields = split;
for (0 .. MAX_COLUMN_INDEX) {
push @{$matrix->[$_]},
defined $fields[$_] ? $fields[$_] : "<undef>";
}
}
return $matrix;
}
sub secondRoutine {
my $matrix = shift;
for my $row (0 .. $#{$matrix->[0]}) {
for my $col (0 .. MAX_COLUMN_INDEX) {
print "Row $row Col $col = $matrix->[$col][$row]";
}
}
return;
}
'
q w e
a s
z
Row 0 Col 0 = q
Row 0 Col 1 = w
Row 0 Col 2 = e
Row 1 Col 0 = a
Row 1 Col 1 = s
Row 1 Col 2 = <undef>
Row 2 Col 0 = z
Row 2 Col 1 = <undef>
Row 2 Col 2 = <undef>
| [reply] [d/l] [select] |