最简单的方法来匹配字符串数组在Perl中进行搜索? [英] Simplest way to match array of strings to search in perl?

查看:1047
本文介绍了最简单的方法来匹配字符串数组在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆