Как я могу отфильтровать массив без использования цикла в Perl? - PullRequest
27 голосов
/ 18 октября 2010

Здесь я пытаюсь отфильтровать только те элементы, которые не имеют подстроки world, и сохранить результаты обратно в тот же массив. Как правильно сделать это в 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.
$

Я хочу передать массив в качестве аргумента подпрограмме.

Я знаю, что одним из способов было бы что-то вроде этого

$ 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
$

Я хочу знать, есть ли способ сделать это без цикла (используя некоторую простую фильтрацию).

Ответы [ 4 ]

35 голосов
/ 18 октября 2010

Это было бы 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";
11 голосов
/ 18 октября 2010

Использование grep:

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

Например:

@arrf = remove_worlds @arr;

Использование grep является наиболее естественным подходом для вашей конкретной задачи, но для полноты вы также можете сделать это с помощью map:

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

Здесь немного сложно, но map дает вам ловушку на тот случай, если вы хотите обработать отфильтрованные элементы перед их сбросом.

10 голосов
/ 18 октября 2010

Использовать grep

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

Подробнее perldoc -f grep.

5 голосов
/ 18 октября 2010

Вы можете использовать функцию grep как:

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

Выражение !/world/ вычисляется для каждого элемента массива @arr и возвращается список элементов, для которых выражение, которое оценивается как истинное, возвращается.

Выражение /world/ ищет слово world и верно, оно присутствует. И выражение !/world/ истинно, если строка world отсутствует.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...