Как я могу выбрать определенные элементы из массива Perl? - PullRequest
2 голосов
/ 12 октября 2010

Я хочу найти все элементы в массиве, которые имеют тот же начальный набор символов, что и элемент в другом массиве. Чтобы было понятно:

@array = ("1a","9","3c");
@temp =("1","2","3");

Я хочу напечатать только 1a и 3c. Когда я пытаюсь использовать следующую программу, она распечатывает все элементы в массиве вместо двух, которые я хочу:

foreach $word (@temp)
{
    if( grep /^$word/ , @array) 
    {
        print $_;
    }
}

Любые идеи будут оценены.

Ответы [ 6 ]

3 голосов
/ 12 октября 2010

Этот ответ будет делать то, что хочет OP, а также предотвращает печать дубликатов на экране с помощью поиска хеша.

1 голос
/ 14 октября 2010

Для такого рода проблем хитрость заключается в том, чтобы не сканировать массив больше, чем нужно. Я думаю, что Кнут написал целую книгу об этом. :) Часто мы застреваем в таких ситуациях, потому что слишком привязываемся к тому, что попробовали в первую очередь.

Вы можете создать одно регулярное выражение из всех шаблонов, которые хотите найти, а затем сканировать массив один раз:

use Regexp::Assemble;

my @array = qw( 1a 9 3c );
my @temp  = qw( 1 2 3 );

my $ra = Regexp::Assemble->new;
$ra->add( @temp );

my $pattern = $ra->re;
print "pattern is [$pattern]\n";

print join ' ', grep /\A$pattern/ , @array;

Подобные вещи работают, когда вам все равно, какая часть шаблона совпадает, если она соответствует.

1 голос
/ 12 октября 2010

Если вы хотите сопоставить элементы попарно, вы можете сделать это следующим образом:

for my $i (0..$#array) {
    print $array[$i], "\n" if $array[$i] =~ /^$temp[$i]/
}

В противном случае вы можете использовать grep:

for my $i (0..$#array) {
    print "$array[$i]\n" if grep /^$temp[$i]/, @array;
}
0 голосов
/ 12 октября 2010

Чтобы избежать пустых строк, если grep возвращает пустой список:

#!/usr/bin/perl
use strict;
use warnings;
use 5.10.1;

my @array = qw(1a 9 3c 1g);
my @temp =(1, 2, 3);
foreach my $word(@temp) {
  my @l = grep{/^$word/}@array;
  say "@l" if @l;
}

Выход:

1a 1g
3c
0 голосов
/ 12 октября 2010
map { print "$_\n" } grep { my $a = $_; grep {$a =~ /^$_/} @temp } @array

По сути, внешний grep выбирает элементы, для которых 1 или более элементов в @temp соответствует внутреннему регулярному выражению, то есть он выбирает все элементы, которые начинаются с одного (или более) элементов в @temp.

0 голосов
/ 12 октября 2010

Когда я пытаюсь использовать следующую программу, она распечатывает все элементы в массиве вместо двух, которые я хочу.

Нет, это не так.Как написано, ничего не печатает.При строгом включении он печатает «Глобальный символ« $ temp »требует явной упаковки».

Исправляя эту очевидную опечатку и включая предупреждения, он печатает «Использование неинициализированного значения $ _ в печати» дважды.

Пожалуйста, не тратьте наше время, показывая нам код, который либо не компилируется, не делает то, что вы говорите.Не перепечатывайте код на этом сайте - вырезайте и вставляйте фактический код, который вы используете.

Решение вашей проблемы будет примерно таким:

#!/usr/bin/perl

use strict;
use warnings;

my @array = ("1a","9","3c");
my @temp =("1","2","3");

foreach my $word (@temp) {
  print grep /^$word/ , @array;
}

Но естьвероятно, более эффективные способы сделать это.

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