An elegant way to return the index of the last nonzero element in Perl?

I am in search of the index of the last nonzero element in the array. So, considering:

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 have done this:

for my $i (0 .. $#array) {
    $indexLastNonZero = $i if $array[$i] != 0;
};

I work, but for some reason I can't help but feel that there should be a super elegant (smarter? Good? More efficient?) Way to do this in perl. I looked at List :: Utils, but did not find a nice way there and would like to use a module independent of it.

Any thoughts?

Greetings

+4
source share
6 answers

Start at the end of the array and work backward until you find a nonzero 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 test is $i >= 0intended to protect against the edge where all elements are equal to zero. In this case, the resulting value $iis -1.

+5

List:: MoreUtils :

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
+13
my @array = (0,0,5,9,0,0,0,7,0,3,0,0);
my ($indexLastNonZero) = grep $array[$_], reverse 0 .. $#array;
+5
source

You can use List::Utilwhich is in the kernel:

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"; 
+1
source

Destructive approach: first take a copy of the array:

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
0
source
sub last_true {
    pop and return scalar @_ while @_;
    undef;
}

my $index = last_true(@foo);
0
source

All Articles