4

how to splice a reference array using perl? I'm trying to remove certain elements from a reference array used in a function.

    &removeELement(@spliceArray);

    sub removeELement
    {
        my $ref_to_spliceArray = shift;

        foreach my $i (0 .. $#$ref_to_spliceArray)
        {
              if($ref_to_spliceArray->[$i] == /failed/)
              {
                    splice $ref_to_spliceArray->[$i],1; # this syntax does not work...
              }
        }
    }

4 Answers 4

2

You can get the desired behavior with a couple of changes to your code.

  • If you delete an element of the array, the index of the next element is now the same as the old value’s index. You can’t blindly iterate over 0 .. $#ref_to_spliceArray.
  • The regex bind operator is =~ and not ==.
  • Attempted regex matches against the undefined value may trigger warnings.
  • Pass an array to splice, not an individual element of the array.

The code below fixes these issues.

sub removeElement
{
  my $ref_to_spliceArray = shift;

  my $i = 0;
  while ($i <= $#$ref_to_spliceArray)
  {
    if (defined $ref_to_spliceArray->[$i]
          && $ref_to_spliceArray->[$i] =~ /failed/)
    {
      splice @$ref_to_spliceArray, $i, 1;
    }
    else {
      ++$i;
    }
  }
}

Modify your call to be

&removeElement(\@spliceArray);

Note that this syntax will appear archaic to modern eyes. Think about operating on the array as a whole rather than peeking and poking one element at a time. In this simple case, you don’t need to go to the trouble of defining another sub.

@spliceArray = grep !(defined && /failed/), @spliceArray;

That is, @spliceArray should contain only those elements that do not match the regex. The defined check prevents warnings about undefined values that may be present in @spliceArray.

Sign up to request clarification or add additional context in comments.

Comments

0

For using splice correctly, I'd suggest taking a look at the splice man page.

If using a reference, just dereference it: @$aref instead of just $aref.

For solving the problem at hand, consider using grep instead. Here's an example using the Windows (double-quotes!) command-line:

perl -lwe "$x = [qw/a b failed d/]; print for grep ! m/failed/, @$x"

One more thing: use regular expressions with =~ and !~, not ==.

And you are using strict, aren't you? Always use strict, always!

Comments

0

It's usually a bad idea to try to remove elements from a list you are iterating over. Try using grep to create a new list containing only those elements you want to keep, and assign back to the original reference.

sub removeElement {
    my $ref_to_Array = shift;

    @$ref_to_Array = grep { ! /failed/ } @$ref_to_array;
}

&removeElement(\@someArray);

Notice you need to pass a reference to your array to the function.

The call to splice you were probably looking for, by the way, was

splice @$ref_to_spliceArray, $i, 1

Comments

0

You could simply use grepfor this:

my @array = qw/foo bar baz qux/;
@array = grep { ! m/baz/ } @array;
# @array now contains foo bar qux

Your code has several mistakes:

  • == isn't the same thing as =~
  • You did not specify the offset and length to splice (eg. splice $@aray, $i, 1)
  • After splice removed and element from your array the index $i will be incorrect, because you removed and item from the array and you'll be checking your array against elements which will not exist.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.