2012-02-06 3 views
0

У меня есть два массива @input0 и @input1. Мне нужен цикл for, который проходит через каждое значение в @input1, и если это значение существует в @input0, значение сохраняется в новом массиве @input.Поиск значений в массиве с использованием Perl

Все массивы содержат только цифры. Есть максимум 10 номеров на один элемент массива (см ниже):

@input0 = {10061 10552 10553 10554 10555 10556 10557 10558 10559 10560, 10561 10562 10563 10564 10565 10566 10567 10573 10574 10575, ...} 

@input1 = {20004 20182 ...} 
+1

'@ input0 = {10061 10552 ...., 10561 ...}' недопустимый синтаксис perl и выдавал бы ошибки, такие как 'Number found where operator expected'. Вам нужно будет указать строки «10061 10552 ...» '. Кроме того, фигурные скобки '{}' создают хеш-ссылку. Вы хотите регулярные parens '()' при назначении массиву. – TLP

ответ

2

Короткий, сладкий и медленно:

my @input = grep $_ ~~ @input0, @input1; 

Многословные и быстрее для цикла:

my %input0 = map {$_, 1} @input0; 
my @input; 

for (@input1) { 
    push @input, $_ if $input0{$_}; 
} 
+0

Smart Match работает только в Perl 5.10 и работает и не работает раньше. – DVK

+1

Это также медленнее для больших массивов, так как это сканирование O (N * M), в отличие от I (N + M), как map + grep – DVK

+0

Это правда, но вы избили меня до идиоматического решения. Если что-то, однако, это решение упрощает на первый взгляд, что он создает пересечение двух массивов. – flesk

7

Наиболее краткий и идиоматическим способом для достижения этой цели в Perl не через использование «для» цикла, но map и grep

my %seen0 = map { ($_ => 1) } @input0; 
my @input = grep { $seen0{$_} } @input1; 

Если вы специально хотите для цикла, объясните, пожалуйста, почему карта/Grep подход не работает (если это не домашнее задание, в этом случае вопрос должен быть помечен как один)

+0

+1. Идиоматическое решение является идиоматическим. – flesk

+0

Это не работает. Я предполагаю, потому что у меня более одного числа на элемент массива (до 10, разделенных пробелами). Извините, надо было бы это упомянуть. Итак, лучше ли сначала разбивать массив на отдельные числа на элемент? Спасибо –

+0

@charleshendry - если у вас есть строка, разделенная пробелом, она не называется «массивом». Вам нужно дать более точные описания и примеры – DVK

1

Вы также можете использовать hashslice + Grep: ответ

my %tmp ; 
@tmp{@input0} = undef ; # Fill all elements of @input0 in hash with value undef 
my @input = grep { exists $tmp{$_} } @input1 ; # grep for existing hash keys 
0

DGW был почти там, но содержал несколько вещей, которые Арен Лучшая практика. Я считаю, что это лучше:

my %input0_map; 
@input0_map{ @input0 } =(); 
my @input = grep { exists $input0_map{$_} } @input1; 

Вы не должны назвать переменную «TMP», если это не в очень небольшом объеме. Поскольку этот фрагмент кода не завернут в скобках, мы не знаем, насколько большой объем.

Вы не должны назначать в хэш-срез с одним «undef», потому что это означает, что первый элемент присваивается этим литералом undef, а другим элементам присваиваются неявные undefs. Он будет работать, но это плохой стиль. Либо присвойте им все значение, либо назначьте их ВСЕ, неявно (как это происходит, если мы назначим из пустого списка).

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