2015-01-14 3 views
0

Привет, У меня проблема с моей программой, я написал код ниже и возвращает ожидаемый результат. Однако меня интересует только первое и последнее появление матчей. Как мне это сделать?Соответствие:

foreach (@array) 
{ 
    $element = $_; 
    foreach(@array2) 
    { 
     if($_ =~ s/($element)//ig) 
     { 
      print "$_ \n"; 
     } 
    } 
} 

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

+3

Это кажется [проблема XY] (http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). Не могли бы вы объяснить, что именно вы пытаетесь сделать, а не как это сделать? Там может быть лучший подход, чем использование вложенных циклов. – ThisSuitIsBlackNot

+0

Поместите совпадения в список, а не распечатывайте их. Затем после цикла напечатайте первый и последний элементы списка. – Barmar

+1

Вы используете подстановку, которая * removeg * все найденные совпадения, и мне интересно, понимаете ли вы, что это может повлиять на то, какие строки совпадают позже. Например, если '@ array' содержит' ('abc', 'def') ', а один элемент' @ array2' - 'dabcef', тогда первый проход скажет, что' abc' был найден *, но измените элемент от 'dabcef' до' def' *. Таким образом, в следующем проходе будет указано, что 'def' также соответствует, что было неверно до модификации. Это намеренно? – Borodin

ответ

0

Может возможно сделать это

foreach (@array) 
{ 
    $first = ""; 
    $last = ""; 
    $element = $_; 
    foreach(@array2) 
    { 
     if($_ =~ s/($element)//ig) 
     { 
      if (!length($first)){ 
       $first = $_; 
      } 
      else { 
       $last = $_; 
      } 
     } 
    } 
    if (length($first) && length($last)) { 
     print "\n----------\nfirst = '$first'\nlast = '$last'"; 
    } 
} 
+0

Вы пропустили скобку «if (! Length ($ first) {» line - close bracket. Кроме того, ваша идея работала как шарм! Спасибо – user3423572

+0

@ user3423572 - Исправлено, спасибо! – sln

1
foreach my $elm2 (@array2) { 
    my $state = 'start'; 
    my $first, $last; 

    foreach my $elm1(@array1) { 
      if (($state eq 'start') && ($elm1 =~ m/$elm2/i)) { 
       $first = "$elm1"; 
       $state = 'last'; 
      } 
      elsif (($state eq 'last') && ($elm1 =~ m/$elm2/i)) { 
       $last = $elm1; 
      } 
    } 
    print "$elm2,$first,$last\n"; 
} 
+0

Если есть только одно совпадение, это будет печатать дважды. – dgw

+0

Там я исправил его. – sam

0

Полностью забыл о Grep.

foreach my $elm2 (@array2) { 
     my @matches = grep(/$elm2/i, @array1); 
     if (@matches && (scalar (@matches > 1))) { 
     print "$elm2,$matches[0], $matches[-1]\n"; 
     } 
     elsif (@matches) { 
     print "$elm2,$matches[0]\n"; 
     } 
     else {print "no matches\n";}; 
} 
0

немного поздно, но это то, что я думаю, вы могли бы использовать

Найти первый матч

if ($_ =~ m/($element)/) { print $1; } 

Найти последний матч

if ($_ =~ m/.*($element)/) { print $1; } 
+0

конечно, если есть только 1, шаблон будет напечатан дважды – lightbringer

0

Предполагая, что вы хотите проверить, какие элементы @array2 соответствуют любому шаблону в @array и распечатывают первый a Последнее последнее из них, проще всего создать регулярное выражение чередования из содержимого @array и фильтра @array2, используя это.

Как это

my $re = join '|', @array; # Build a regex 
$re = qr/$re/;    # Compile it 

my @matches = grep /$re/, @array2; 
print "$_\n" for @matches[0,-1]; 
Смежные вопросы