7

While executing a script, I need to delete multiple elements (these elements are not sequential) of an array. I will get my array and indexes while executing the script.

For example:

I may get an array and list of indexes like below:

my @array = qw(one two three four five six seven eight nine);

my @indexes = ( 2, 5, 7 );

I have below subroutine to do this:

sub splicen {
    my $count     = 0;
    my $array_ref = shift @_;

    croak "Not an ARRAY ref $array_ref in $0 \n"
        if ref $array_ref ne 'ARRAY';

    for (@_) {
        my $index = $_ - $count;
        splice @{$array_ref}, $index, 1;
        $count++;
    }

    return $array_ref;
}

If I call my subroutine like below:

splicen(\@array , @indexes);

That works for me but:

Is there any better way to do this?

Miller
  • 34,962
  • 4
  • 39
  • 60
  • 1
    Provide example input and output to make the question (and goal) more clear. If the given code fails to produce the expected out, also explain that. – user2864740 Aug 15 '14 at 08:55
  • See: http://stackoverflow.com/a/25322103/372239 – Toto Aug 15 '14 at 09:45

2 Answers2

9

If instead you splice from the end of the array, you won't have to maintain the offset $count:

sub delete_elements {
    my ( $array_ref, @indices ) = @_;

    # Remove indexes from end of the array first
    for ( sort { $b <=> $a } @indices ) {
        splice @$array_ref, $_, 1;
    }
}
Miller
  • 34,962
  • 4
  • 39
  • 60
LeoNerd
  • 8,344
  • 1
  • 29
  • 36
  • Just to be sure, you should sort the `@indices` array yourself or at least document that you'll expect a sorted array. – dgw Aug 15 '14 at 11:02
1

Another way think about it is to build a new array rather than modifying the original:

my @array   = qw(one two three four five size seven eight nine);
my @indexes = (2, 5, 7);
my %indexes = map { $_ => 1 } @indexes;
my @kept    = map { $array[$_] } grep { ! exists $indexes{$_} } 0 .. $#array;
FMc
  • 41,963
  • 13
  • 79
  • 132
  • That costs me an extra hash and array @FMc – Malli Paritala Aug 15 '14 at 13:29
  • This will also break (i.e. strengthen) weak references, if there were any in the original array. Perhaps a minor point, but one that's bitten me before now. `splice` on the original array won't disturb the remaining elements in this way. – LeoNerd Aug 15 '14 at 16:28