Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

Unable to remove items from an array that are empty ' '

by nat47 (Sexton)
on Apr 25, 2015 at 21:06 UTC ( [id://1124707]=perlquestion: print w/replies, xml ) Need Help??

nat47 has asked for the wisdom of the Perl Monks concerning the following question:

When I use Data Dumper to view my array I see this

$VAR1 = 'stuff'; $VAR2 = ''; $VAR3 = 'stuff'; $VAR4 = ''; $VAR5 = '10'; $VAR6 = ''; $VAR7 = '-'; $VAR8 = '';
This is how I tried to remove it, and it didn't work:
do { $a_counter = 0; foreach my $x(@left_split) { if($x eq '') { splice @left_split, $a_counter-1, 1; $bool = 1; last; } } }

Replies are listed 'Best First'.
Re: Unable to remove items from an array that are empty ' '
by choroba (Cardinal) on Apr 25, 2015 at 21:14 UTC
    Where do you increment $a_counter?

    This is how you can fix it:

    #!/usr/bin/perl use warnings; use strict; use Data::Dumper; my @left_split = ('stuff', '', 'stuff', '', '10', '', '-', ''); my $index = 0; while ($index <= $#left_split) { if ('' eq $left_split[$index]) { splice @left_split, $index, 1; } else { ++$index; } } print Dumper \@left_split;

    But I would simply use grep:

    @left_split = grep '' ne $_, @left_split;
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re: Unable to remove items from an array that are empty ' '
by toolic (Bishop) on Apr 25, 2015 at 21:18 UTC
    grep length is one way:
    use warnings; use strict; use Data::Dumper; my @ls = ('stuff', '', 'stuff', '', 10, '', '-', ''); @ls = grep {length} @ls; print Dumper(\@ls); __END__ $VAR1 = [ 'stuff', 'stuff', 10, '-' ];
Re: Unable to remove items from an array that are empty ' '
by davido (Cardinal) on Apr 25, 2015 at 22:07 UTC

    One problem is modifying the size of an array while iterating over it with a foreach loop is unhealthy. If we were programming in C++ one would say that the splice invalidates the iterator. We don't have such well defined terminology for what you're doing, in Perl. But the effect is similar.

    Additionally, even if this did work as you intended, you're doing way too much work. To splice out an element within an array, all elements to the right need to shift leftward one. So each and every splice is a linear operation. And the general algorithm of filtering an array using a loop and splice will have quadratic growth. If you're willing to trade memory for speed, a better solution is one that populates a new array (even if internally) with the elements filtered from the original array. This sort of algorithm has a linear order of growth as the array's size grows.

    Not only is this better algorithm an order of magnitude faster, it's also far easier to write, especially since that's what the Perl built-in grep function does just that:

    my @array = ( 'stuff', '', 'stuff', '', '10', '', '-', '' ); @array = grep { $_ ne '' } @array;

    If you want to remove all elements that have either an empty string, or are not defined, you could just do this:

    @array = grep length, @array;

    This works because length returns a false value for empty strings, as well as for containers that are 'undef'.

    my @array = ( 'stuff', '', 'stuff', '', '10', '', '-', '' );

    So on the first iteration


    Dave

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1124707]
Approved by toolic
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others surveying the Monastery: (4)
As of 2024-03-28 20:00 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found