最简单的方法来匹配字符串数组在Perl中进行搜索? [英] Simplest way to match array of strings to search in perl?
问题描述
我想要做的就是检查字符串数组对我的搜索字符串,并得到相应的键,所以我可以保存它。有没有用Perl这样做的神奇的方式,还是我注定要使用一个循环?如果是这样,什么是最有效的方式做到这一点?
我是比较新的Perl的(我只写了其他2个脚本),所以我不知道很多神奇的是,只是Perl是魔术= D
引用数组:(1 ='佳能',2 ='惠普',3 ='索尼')
搜索字符串:索尼的Cyber-shot DSC-S600
最终结果是:3
更新:
根据讨论中 href=\"http://stackoverflow.com/questions/3019925/is-map-a-loop\">这个问题,这取决于你的意图/标准什么是不使用循环,下面的地图
基于解决方案(参见选项#1 )可能是最简洁的解决方案,但前提是你不认为地图
循环(答案短的版本是:这是一个循环就实现/性能,它不是从语言观理论上讲循环)。 假设,通过建立一个常规的前$ P $你不关心你是否获得3或索尼作为答案,你可以不用在简单的情况下,循环pssion用或逻辑( |
)从数组,像这样的:
我@strings =(佳能,惠普,索尼);
我的$ search_in =索尼的Cyber-shot DSC-S600
我的$ combined_search =加入(|,@字符串);
我@which_found =($ search_in =〜/($ combined_search)/);
打印$ which_found [0] \\ n;
从我的测试运行
结果:索尼
常规前pression会(一旦变量 $ combined_search
是由Perl的插值)采取的形式 /(佳能|惠普|索尼)/
这是你想要的。
这将无法正常工作,就是如果有任何字符串包含regex的特殊字符(如 |
或)
) - 在这种情况下,你需要躲避他们。
注意:我个人认为这个有点作弊,因为为了落实加入()
,Perl本身必须某处做一个循环内interpeter。所以,这个答案可能无法满足你的愿望,保持循环少,取决于你是否想要避免出于性能考虑,一个循环,对有清洁剂或短code。
P.S。要获得3,而不是索尼,你将不得不使用一个循环 - 无论是在一个明显的方式,在骨子里的循环做1场;或使用节省你自己写的循环,但将有呼叫下一个循环。库
我公司将提供3替代解决方案。
#1选项: - 我的最爱。使用地图,我个人仍然认为一个循环:
我@strings =(佳能,惠普,索尼);
我的$ search_in =索尼的Cyber-shot DSC-S600
我的$ combined_search =加入(|,@字符串);
我@which_found =($ search_in =〜/($ combined_search)/);
打印$ which_found [0] \\ n;
死未找到除非@which_found;
我的$ strings_index = 0;
我的%strings_indexes = {图$ _ => $ strings_index ++} @strings;
我的$指数= 1 + $ strings_indexes {$ which_found [0]};
#需加1,因为在Perl数组是零索引开始,你想3
#2选项:使用的背后隐藏着一个很好的CPAN库方法的循环:
使用List :: MoreUtils QW(firstidx);
我@strings =(佳能,惠普,索尼);
我的$ search_in =索尼的Cyber-shot DSC-S600
我的$ combined_search =加入(|,@字符串);
我@which_found =($ search_in =〜/($ combined_search)/);
死未找到!除非@which_found;
打印$ which_found [0] \\ n;
我的$ index_of_found = 1 + firstidx {$ _当量$ which_found [0]} @strings;
#需加1,因为在Perl数组是零索引开始,你想3
#3选项:这里是明显的循环方式:
我的$ found_index = -1;
我@strings =(佳能,惠普,索尼);
我的$ search_in =索尼的Cyber-shot DSC-S600
我的foreach $指数(0 .. $#字符串){
接下来,如果$ search_in〜/ $字符串[$指数] /!;
$ found_index = $指数;
持续; #退出循环的早期,这就是为什么我没有用地图在这里
}
#$检查对found_index -1;如果你想3,而不是2加1。
What I want to do is check an array of strings against my search string and get the corresponding key so I can store it. Is there a magical way of doing this with Perl, or am I doomed to using a loop? If so, what is the most efficient way to do this?
I'm relatively new to Perl (I've only written 2 other scripts), so I don't know a lot of the magic yet, just that Perl is magic =D
Reference Array: (1 = 'Canon', 2 = 'HP', 3 = 'Sony')
Search String: Sony's Cyber-shot DSC-S600
End Result: 3
UPDATE:
Based on the results of discussion in this question, depending on your intent/criteria of what constitutes "not using a loop", the map
based solution below (see "Option #1) may be the most concise solution, provided that you don't consider map
a loop (the short version of the answers is: it's a loop as far as implementation/performance, it's not a loop from language theoretical point of view).
Assuming you don't care whether you get "3" or "Sony" as the answer, you can do it without a loop in a simple case, by building a regular expression with "or" logic (|
) from the array, like this:
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";
Result from my test run: Sony
The regular expression will (once the variable $combined_search
is interpolated by Perl) take the form /(Canon|HP|Sony)/
which is what you want.
This will NOT work as-is if any of the strings contain regex special characters (such as |
or )
) - in that case you need to escape them
NOTE: I personally consider this somewhat cheating, because in order to implement join()
, Perl itself must do a loop somewhere inside the interpeter. So this answer may not satisfy your desire to remain loop-less, depending on whether you wanted to avoid a loop for performance considerations, of to have cleaner or shorter code.
P.S. To get "3" instead of "Sony", you will have to use a loop - either in an obvious way, by doing 1 match in a loop underneath it all; or by using a library that saves you from writing the loop yourself but will have a loop underneath the call.
I will provide 3 alternative solutions.
#1 option: - my favorite. Uses "map", which I personally still consider a loop:
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 option: Uses a loop hidden behind a nice CPAN library method:
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 option: Here's the obvious loop way:
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.
这篇关于最简单的方法来匹配字符串数组在Perl中进行搜索?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!