my $doc_num;
my $tmp_doc_num;
my @doc_nums;
my @doc;
foreach( @doc_nums ) {
@doc = ();
$doc_num = substr( $_, 0, 7 );
foreach( @raw ) {
@fields = split( /,/, $_ );
if( $fields[0] eq "AIP65" ) {
$tmp_doc_num = substr( $fields[5], 0, 7 );;
} else {
$tmp_doc_num = substr( $fields[4], 0, 7 );
}
( $tmp_doc_num eq $doc_num ) ? push( @doc, $_ ) : next;
}
push( @docs, \@doc );
}
Thanks in advance,
Casey
That's because you're reusing the same array each time through the loop. There's only one @doc - the one you declared outside the loop. You push a bunch of references to that array onto the @docs list, but since it's the same @doc, they'll all be the same.
Instead, try one of these idioms. My favourite is to just declare @doc inside your loop:
foreach( @doc_nums ) {
my @doc;
This will create a new array each time. That allows the push to get a different reference. And since Perl does reference counting right, those arrays, though out of scope at the end of the loop, won't be cleared away because the @docs array still refers to them.
Second option: create a copy of the @doc array, and push that on to the list:
push @docs, [ @doc ];
This will be a bit slower if @doc can be large, but is nice that it's explicitly obvious. That said, the first option is such a common idiom that it's pretty obvious after a while, too.
Hope that helps :-)
Move my @doc inside the loop so you get a new instance of the doc array each time through. Consider:
use strict;
use warnings;
my @doc_nums = qw(1 2 3 4 5 6 7 8 9);
my @docs;
foreach( @doc_nums ) {
my @doc;
push @doc, int rand 10 for 1..3;
push @docs, \@doc;
}
print "@$_\n" for @docs;
Prints:
9 5 8 9 5 7 2 2 1 3 0 4 8 6 4 6 1 7 6 5 5 8 6 9 9 9 7
or you could change the reference to a copy:
use strict;
use warnings;
my @doc_nums = qw(1 2 3 4 5 6 7 8 9);
my @docs;
my @doc;
foreach( @doc_nums ) {
@doc = ();
push @doc, int rand 10 for 1..3;
push @docs, [@doc];
}
print "@$_\n" for @docs;
push( @docs, \@doc );
You need push( @docs, [ @doc ] );. The reason is that if you use a backslash, you are taking a reference to the same variable, which contains differents things each time but the reference "points to" the same location in memory. Using square brackets, you create a new reference each time. That's the difference.
Update: To make things clearer, look at this program and its output:
use Data::Dumper;
my (@c, @d);
foreach (1..3) {
@c[0..4] = (rand) x 2;
push @d, \@c;
}
print Dumper \@d;
@d=(); ## reset @d
foreach (1..3) {
@c[0..4] = (rand) x 2;
push @d, [@c];
}
print Dumper \@d;
__END__
$VAR1 = [
[
'0.566846394018409',
'0.566846394018409'
],
$VAR1->[0],
$VAR1->[0]
];
$VAR1 = [
[
'0.872105763616624',
'0.872105763616624'
],
[
'0.0550789852978433',
'0.0550789852978433'
],
[
'0.130973801235072',
'0.130973801235072'
]
];
The first time, @d is populated with references to the same information ([mod://Data::Dumper] shows $VAR1->[0] instead of repeating it). The second example shows different numbers because [ ] create different references each time.
--
David Serrano
The [] makes an anonymous copy of the array and in effect returns an reference to it. {} can be used in similar fashion to create an anonymous copy of a hash.
Actually you create a copy each time with the [], and push a reference to the copy.
In the original code the push was creating a new reference each time - to the same instance.
Any time you're not sure what's going on with a complex datastructure, I recommend you take a look at it using one (or more) of the techniques outlined here:
How can I visualize my complex data structure?
You might also wish to take a look at:
node 137108
node 69927
HTH,
perlmonks.org content © perlmonks.org and caseydentinger, GrandFather, Hue-Bond, planetscape, Tanktalus
prlmnks.org © 2006 edmund von der burg (eccles & toad)
v 0.03