2010-10-12 2 views
2

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

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

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

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

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

+2

Вы должны принять ответы на некоторые из ваших предыдущих вопросов :) –

+1

Выполнено. Понятия не имею, что я должен был это сделать. – omgpython

+0

Я бы предложил вам объявить переменные с помощью 'my', например. 'my @array = (..)', 'foreach my $ word (@temp) {..}' и включить строгую и предупреждения –

ответ

3

Этот ответ будет делать то, что ОП хочет, а также предотвратить любые дубликаты из печати на экране через использование хэш-поиска.

#!/usr/bin/perl 

use strict; 
use warnings; 

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

my %dups_hash; 

for my $w (@temp) { 
    my ($match) = grep /^$w/, @array; 

    # Need to check if $match is defined before doing the hash lookup. 
    # This suppresses error messages for uninitialized values; if defined($match) is 
    # false, we short circuit and continue in the loop. 
    if(defined($match) && !defined($dups_hash{$match})) { 
     print $match; 
    } 
} 
+0

Работает отлично. Благодаря :) – omgpython

1

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

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; 
} 
+2

Я думаю, что это слишком ограничительно ... OP просто сказал, что хочет напечатать элемент, если он началось с ЛЮБОГО из элементов в другом массиве. Это накладывает взаимно однозначное отображение. –

+0

Я не могу отменить мой -1 по какой-то причине ... Можете ли вы сделать мне одолжение и отредактировать это еще раз, чтобы я мог его отменить? –

+0

Вторая с grep все еще не делает то, что хочет OP. Он печатает слово, которое вы используете, для grep вместо значения в массиве. – Weegee

0

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

Нет, это не так. Как написано, оно ничего не печатает. При строгом включении он печатает «Глобальный символ» $ 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; 
} 

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

+1

Это может привести к дублированию (если '@ temp' имеет несколько элементов, которые запускаются одинаково и поэтому могут сопоставлять что-то в' @ array' с каждым из них). –

+0

Спасибо за ваш ответ. И я скопировал пасту «фактический код и вывод». Я не использую строгий, хотя я знаю его стандарт. Я просто использую perl для быстрой обработки строк, хотя я знаю, что должен использовать строгую. – omgpython

-1
map { print "$_\n" } grep { my $a = $_; grep {$a =~ /^$_/} @temp } @array 

В основном, внешний grep выбирает элементы, для которых один или более из элементов в @temp соответствует внутреннему regex--, которое он выбирает все элементы, которые начинаются с одной (или более) элементов @temp.

+0

umm..quick followup..Что бы вы хотели напечатать только первое совпадение? – omgpython

-1

Чтобы избежать пустых строк, если возвращение 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

Может ли нижестоящий объяснить, почему? – Toto

1

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

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

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; 

Такого рода вещи работает, когда вы не заботитесь, какая часть рисунка если он совпадает.

Смежные вопросы