Ответ 1
UPDATE:
Основываясь на результатах обсуждения в этом вопросе, в зависимости от ваших намерений/критериев того, что составляет "не используя цикл", решение map
ниже (см. " Вариант № 1), может быть самым кратким решением при условии, что вы не рассматриваете цикл map
(короткая версия ответов: это цикл в отношении реализации/производительность, это не цикл с теоретической точки зрения).
Предполагая, что вам не важно, получите ли вы "3" или "Sony" в качестве ответа, вы можете сделать это без цикла в простом случае, создав регулярное выражение с помощью "или" логика (|
) из массива, например:
my @strings = ("Canon", "HP", "Sony");
my $search_in = "Sony Cyber-shot DSC-S600";
my $combined_search = join("|",@strings);
my @which_found = ($search_in =~ /($combined_search)/);
print "$which_found[0]\n";
Результат моего тестового прогона: Sony
Регулярное выражение будет (после того, как переменная $combined_search
будет интерполирована Perl) примет форму /(Canon|HP|Sony)/
, которую вы хотите.
Это НЕ будет работать как есть, если какая-либо из строк содержит специальные символы регулярных выражений (например, |
или )
) - в этом случае вам нужно избежать их
ПРИМЕЧАНИЕ. Я лично считаю это несколько обманом, потому что для реализации join()
Perl сам должен делать петлю где-то внутри интерпретатора. Таким образом, этот ответ может не удовлетворить вашему желанию оставаться без петли, в зависимости от того, хотите ли вы избежать цикла для соображений производительности, чтобы иметь более чистый или более короткий код.
P.S. Чтобы получить "3" вместо "Sony", вам придется использовать цикл - либо очевидным образом, выполнив 1 совпадение в цикле под всем этим; или с помощью библиотеки, которая избавляет вас от написания цикла самостоятельно, но будет иметь петлю под вызовом.
Я предоставлю 3 альтернативных решения.
# 1: - мой любимый. Использует "карту", которую я лично все еще рассматриваю как цикл:
my @strings = ("Canon", "HP", "Sony");
my $search_in = "Sony Cyber-shot DSC-S600";
my $combined_search = join("|",@strings);
my @which_found = ($search_in =~ /($combined_search)/);
print "$which_found[0]\n";
die "Not found" unless @which_found;
my $strings_index = 0;
my %strings_indexes = map {$_ => $strings_index++} @strings;
my $index = 1 + $strings_indexes{ $which_found[0] };
# Need to add 1 since arrays in Perl are zero-index-started and you want "3"
# 2 опция: использует цикл, скрытый за хорошим библиотечным методом CPAN:
use List::MoreUtils qw(firstidx);
my @strings = ("Canon", "HP", "Sony");
my $search_in = "Sony Cyber-shot DSC-S600";
my $combined_search = join("|",@strings);
my @which_found = ($search_in =~ /($combined_search)/);
die "Not Found!"; unless @which_found;
print "$which_found[0]\n";
my $index_of_found = 1 + firstidx { $_ eq $which_found[0] } @strings;
# Need to add 1 since arrays in Perl are zero-index-started and you want "3"
# 3: Здесь очевидный цикл:
my $found_index = -1;
my @strings = ("Canon", "HP", "Sony");
my $search_in = "Sony Cyber-shot DSC-S600";
foreach my $index (0..$#strings) {
next if $search_in !~ /$strings[$index]/;
$found_index = $index;
last; # quit the loop early, which is why I didn't use "map" here
}
# Check $found_index against -1; and if you want "3" instead of "2" add 1.