Reputation: 87
I find myself wanting to find the index of the last non-zero element in an array. So, given:
my @array = (0,0,5,9,0,0,0,7,0,3,0,0);
my $indexLastNonZero = insertElegantMethodHere(@array);
# expect $indexLastNonZero to be equal to 9;
I've done this:
for my $i (0 .. $#array) {
$indexLastNonZero = $i if $array[$i] != 0;
};
I works but somehow I can't help feel there must be a super elegant (smarter? nice? more efficient?) way of doing this in perl. I've looked into List::Utils but not found a nice way there and would like a non-core-module independent method.
Any thoughts?
Cheers
Upvotes: 4
Views: 567
Reputation: 10244
sub last_true {
pop and return scalar @_ while @_;
undef;
}
my $index = last_true(@foo);
Upvotes: 0
Reputation: 61510
You could use List::Util
, which is in core:
use strict;
use warnings;
use List::Util qw(first);
my @array = (0,0,5,9,0,0,0,7,0,3,0,0);
my $index = @array;
first { $index-- && $_ } reverse @array;
print "Last index that is non-zero: $index\n";
Upvotes: 1
Reputation: 7912
Destructive approach so take a copy of the array first:
my @array2 = @array;
while (!pop @array2) {} # Remove up to and including the last non-zero
print scalar @array2; # Size of remaining elements is index of last non-zero
Upvotes: 0
Reputation: 30831
Start at the end of the array and work backwards until you find a non-zero element:
my @array = (0,0,5,9,0,0,0,7,0,3,0,0);
my $i = $#array;
$i-- while $i >= 0 && $array[$i] == 0;
print "The last non-zero element is at index $i\n";
The $i >= 0
test is to guard against the edge case where all elements are zero. In that case the resulting value of $i
is -1.
Upvotes: 5
Reputation: 40499
Use List::MoreUtils for such tasks:
use warnings;
use strict;
use List::MoreUtils;
my @array = (0,0,5,9,0,0,0,7,0,3,0,0);
print List::MoreUtils::lastidx { $_ } @array
Upvotes: 13
Reputation: 50647
my @array = (0,0,5,9,0,0,0,7,0,3,0,0);
my ($indexLastNonZero) = grep $array[$_], reverse 0 .. $#array;
Upvotes: 5