
$element_count = $#Array;
Note that the variable name erroneously states that the variable contains a count of the elements.
Same as 1352.
Although not explicitly obfuscated, the code was very difficult to understand:
@seen{map {
my $la = $_;
map { $la->[$_ & ~1] } 2 .. $#$la;
} $parser->links} = ();
$parser->links here returns a data structure of the form
([P, a,1,b,2,c,3], [Q, d,4,e,5], [R, f,6,g,7,a,8], [S, b,9,e,19,g,11]);
(Apparently it is the return from HTML::LinkExtor.) The goal here is to create a hash whose keys are 1, 2, 3, 4, etc. The values are unimportant.
The author says:
I wouldn't suggest using it, but you might have been considering it.
The code was
my $sortkeys = join " || ",
map "\$a->{\$sortkeys[$_]} cmp \$b->{\$sortkeys[$_]}", 0..$#sortkeys;
Although it's tempting to suggest that it could be replaced with a simpler, $#array-less version:
my $sortkeys = join " || ",
map "\$a->{$_} cmp \$b->{$_}", @sortkeys;
that would not be correct in this case. The author wanted to consider the situation where @sortkeys might contain elements with spaces or other punctuation characters, and the complicated version is required for this.
The poster is constructing a three-dimensional array and wants to replace an index loop with en element loop:
2) I use a[i][j][k] for getting/setting values, its
3 loops and is cumbersume.
3) I'd like to know how I can get/set values without using indexes.
i.e for a simple array:
instead of
for ($i=0; $i <=$#ARR; $i++)
I'd like to use
for $val (@ARR)
But in my case, $val will be a reference until I read the 3rd level,
right?
The post is demonstrating an expression that prints out only elements 1, 3, 5, ... from an array. The demonstration is:
for (0..10) {
my @array1 = (1..$_);
print "$_: >@array1[map 1+2*$_, 0..($#array1-1)/2]<\n";
}
Note the rare use of $#array1-1. This is identical to @array1-2:
for (0..10) {
my @array1 = (1..$_);
print "$_: >@array1[map 1+2*$_, 0..(@array1-2)/2]<\n";
}
With this change, we can move the -2 out of the fraction:
for (0..10) {
my @array1 = (1..$_);
print "$_: >@array1[map 1+2*$_, 0.. @array1/2 -1 ]<\n";
}
This suggests the following transformation:
for (0..10) {
my @array1 = (1..$_);
print "$_: >@array1[map 2*$_-1, 1.. @array1/2 ]<\n";
}
The behavior is now a lot clearer. You can see at a glance how many elements will be printed out: Exactly half (rounded down). It is much more difficult to see this in the original code.
The author appears to believe that $#a=0 is necessary to initialize a previously unused Perl array to contain zero elements:
#!/usr/bin/perl
open (IN,"data");
while (<IN>) {
$#a=0;
$serv="";
$i="";
push (@a,/\s(nam\S+)/g);
for $i(@a) {
($serv)=/(^serv\S+\s+\S+)/;
print "name = $i\n";
print "service = $serv\n";
}
}
In this case, the $#a=0; line is erroneous, since it is inserting an
extra undefined item at the start of the array. The bug can be
fixed by deleting the entire $#a=0; line.
The author has a list of records, each containing a domain name and a count:
@array = (['bath.ac.uk', '46'],
['blackpool.ac.uk', '22'],
... );
The user wants to eliminate duplicate domain names and sum the counts for each unique domain. The code presented sorts the array by domain name; then scans the array, comparing each element's domain with the next element's domain.
@array = sort { $a->[0] <=> $b->[0] } @array;
$c = 0;
for($r = 0;$r <= $#array;$r++)
{
if($array[$r][0] ne $array[$r+1][0])
{
$domains[$c][0] = $array[$r][0];
$domains[$c][1] += $array[$r][1];
$c++;
}
else
{
$domains[$c][0] = $array[$r][0];
$domains[$c][1] += $array[$r][1];
}
}
Note that the code, as presented, may have a bug, because it indexes off the end of the array.
Better code would be:
my (%seen, %count, @unique_domains);
for (@array) {
my ($domain, $count) = @$_;
push @unique_domains, $domain unless $seen{$domain}++;
$count{$domain} += $count;
}
@domains = map [$_, $count{$_}], @unique_domains;
If it's not necessary to preserve the original order of the array, then:
my (%count);
for (@array) {
my ($domain, $count) = @$_;
$count{$domain} += $count;
}
@domains = map [$_, $count{$_}], keys %count;
In either case, $#array is not required.
Return to: Universe of Discourse main page | Perl Paraphernalia | Classes and Talks Program Repair Shop and Red Flags | Survey of $#array Usage
mjd-perl-yak@plover.com