33

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 Answers 4

39

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";
Sign up to request clarification or add additional context in comments.

Comments

13

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.

2 Comments

Good to have the ref links here.
That !/match/ negative matching syntax was critical. I'd been considering map and other solutions but they all seemed too clunky for perl.
11

Use grep

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

For details, perldoc -f grep.

Comments

5

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.

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.