shubster
shubster

Reputation: 825

How do I remove unwanted values from the beginning of an array in Perl?

I am storing values in an array using the push function. The first value in the array is being stored at the fourth element instead of the first element.

For instance, after storing values when I print first element $array[1] it prints space/nothing, but when I print the fourth element, $array[4], it prints the first value. How can I remove unwanted values in the beginning of an array?

Upvotes: 0

Views: 456

Answers (4)

brian d foy
brian d foy

Reputation: 132792

How are you creating the array? Using my amazing powers of ESP, I'm going to guess that you have a split somewhere that is keeping leading empty fields. If I'm wrong, you'll have to tell us more about what you are doing.

You have a bit of an XY problem here. You're asking us how to implement a solution you've already chosen rather than letting us actually fix the problem.

Upvotes: 2

Sinan Ünür
Sinan Ünür

Reputation: 118128

If you want to eliminate all unwanted values:

@array = grep { not value_meets_shubster_s_definition_of_crap($_) } @array;

However, as pointed out by David Dorward, this eliminates unwanted values from the middle of the array as well. To get rid of only the values at the beginning, you can use first_index from List::MoreUtils which might be more efficient than a loop of shifts:

#!/usr/bin/perl

use strict;
use warnings;

use List::MoreUtils qw( first_index );

my @array = ( 0, 1, 0, 2 );
my $begin = first_index { not is_unwanted($_) } @array;

@array = @array[ $begin .. $#array ];

print "@array\n";

sub is_unwanted {
    my ($v) = @_;
    return if $v;
    return 1;
}

__END__

Output:

C:Temp> yjk
1 0 2

Update: My hunch seems to have been wrong:

#!/usr/bin/perl

use strict;
use warnings;

use Benchmark qw( cmpthese );
use List::MoreUtils qw( first_index );

my @array = ( 0, 1, 0, 2, 3, 4, 5, 6, 7, 8, 9 );

cmpthese -10, {
    'first_index' => \&using_first_index,
    'shift'       => \&using_shift,
    'nop'         => \&nop,
};

sub using_first_index {
    my @result = @array;
    my $begin = first_index { not is_unwanted($_) } @result;
    @result = @result[ $begin .. $#result ];
}

sub using_shift {
    my @result = @array;
    shift @result while is_unwanted($result[0]);
}

sub nop { my @result = @array; }

sub is_unwanted {
    my ($v) = @_;
    return if $v;
    return 1;
}

Results:

                Rate first_index       shift         nop
first_index  75767/s          --        -71%        -89%
shift       258810/s        242%          --        -61%
nop         664021/s        776%        157%          --

Upvotes: 0

jsoverson
jsoverson

Reputation: 1717

You can remove elements from the front of an array with the 'shift' operator.

But I think the problem is deeper than that and you're looking at it the wrong way. If you are storing unknown, 'unwanted' values in an array, you need to figure out where and why that is happening and prevent it, not just bypass those to find what you are looking for.

Upvotes: 4

Quentin
Quentin

Reputation: 943510

while ( value_meets_shubster_s_definition_of_crap($array[0]) ) {
  shift @array;
}

sub value_meets_shubster_s_definition_of_crap {
  my $value = shift;
  &helip;
  return true or false;
}

… but it would be better to avoid putting "crap" values onto the array in the first place.

Upvotes: 2

Related Questions