moigescr
moigescr

Reputation: 87

An elegant way of returning the index of the last non-zero element in Perl?

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

Answers (6)

salva
salva

Reputation: 10244

sub last_true {
    pop and return scalar @_ while @_;
    undef;
}

my $index = last_true(@foo);

Upvotes: 0

Hunter McMillen
Hunter McMillen

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

RobEarl
RobEarl

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

Michael Carman
Michael Carman

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

René Nyffenegger
René Nyffenegger

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

mpapec
mpapec

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

Related Questions