更新:
基于this question 中的讨论结果,取决于您对“不使用循环”的意图/标准,下面基于map 的解决方案(请参阅“选项#1 ) 可能是最简洁的解决方案,前提是您不考虑 map 循环(答案的简短版本是:就实现/性能而言,它是一个循环,从语言理论的角度来看,它不是一个循环) .
假设您不关心答案是“3”还是“Sony”,您可以在简单的情况下不使用循环,方法是使用“或”构建正则表达式" 来自数组的逻辑 (|),如下所示:
my @strings = ("Canon", "HP", "Sony");
my $search_in = "Sony's 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 本身必须在解释器内部的某个地方执行循环。因此,此答案可能无法满足您保持无循环的愿望,具体取决于您是否希望出于性能考虑而避免循环,或者是否希望代码更简洁或更短。
附:要获得“3”而不是“Sony”,您必须使用循环 - 以一种明显的方式,通过在其下方的循环中进行 1 次匹配;或者使用一个库来避免你自己编写循环,但在调用下面会有一个循环。
我将提供 3 种替代解决方案。
#1 选项: - 我的最爱。使用“map”,我个人仍然认为是循环:
my @strings = ("Canon", "HP", "Sony");
my $search_in = "Sony's 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's 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's 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.