tags:

views:

111

answers:

4

Here I am trying to filter only the elements that do not have a substring world and store the results back to the same array. What is the correct way to do this in Perl?

$ cat test.pl
use strict;
use warnings;

my @arr = ('hello 1', 'hello 2', 'hello 3', 'world1', 'hello 4', 'world2');

print "@arr\n";
@arr =~ v/world/;
print "@arr\n";

$ perl test.pl
Applying pattern match (m//) to @array will act on scalar(@array) at
test.pl line 7.
Applying pattern match (m//) to @array will act on scalar(@array) at
test.pl line 7.
syntax error at test.pl line 7, near "/;"
Execution of test.pl aborted due to compilation errors.
$

I want to pass the array as an argument to a subroutine.

I know one way would be to something like this

$ cat test.pl 
use strict;
use warnings;

my @arr = ('hello 1', 'hello 2', 'hello 3', 'world1', 'hello 4', 'world2');
my @arrf;

print "@arr\n";

foreach(@arr) {
    unless ($_ =~ /world/i) {
       push (@arrf, $_); 
    }
}
print "@arrf\n";

$ perl test.pl
hello 1 hello 2 hello 3 world1 hello 4 world2
hello 1 hello 2 hello 3 hello 4
$

I want to know if there is a way to do it without the loop (using some simple filtering).

+4  A: 

Use grep

@no_world_for_tomorrow = grep { !/world/ } @feathers;

For details, perldoc -f grep.

Andy Lester
+2  A: 

You can use the grep function as:

@arrf =  grep(!/world/, @arr);

The expression !/world/ is evaluated for each element of the array @arr and a list of elements which which the expression evaluated to be true is returned.

The expression /world/ searches for the word world and is true it's present. And the expression !/world/ is true if the string world is absent.

codaddict
+8  A: 

That would be grep():

#!/usr/bin/perl

use strict;
use warnings;

my @arr = ('hello 1', 'hello 2', 'hello 3', 'world1', 'hello 4', 'world2');
my @narr = ( );

print "@arr\n";
@narr = grep(!/world/, @arr);
print "@narr\n";
Ruel
+3  A: 

Use grep:

sub remove_worlds { grep !/world/, @_ }

For example:

@arrf = remove_worlds @arr;

Using grep is the most natural fit for your particular problem, but for completeness, you can also do it with map:

sub remove_worlds { map /world/ ? () : $_, @_ }

It's a bit klunky here, but map gives you a hook in case you want to process the filtered elements before discarding them.

Greg Bacon