Perl smartmatch运算符或grep检查数组中是否存在值
在阅读了最近关于检查数组中是否存在值的Perl问题后,我开始思考如何执行此操作。我看到大多数人在表格中推荐grep选项Perl smartmatch运算符或grep检查数组中是否存在值,perl,Perl,在阅读了最近关于检查数组中是否存在值的Perl问题后,我开始思考如何执行此操作。我看到大多数人在表格中推荐grep选项 if (!grep { $input_day eq $_ } @days ) { say "Grep Invalid Day"; } 然而,当我读到这个问题时,我的第一个问题跳到了智能匹配操作符 unless ( $input_day ~~ @days ) { say "Smart Invalid Day"; } 所以我想知道使用grep是否比smart-m
if (!grep { $input_day eq $_ } @days ) {
say "Grep Invalid Day";
}
然而,当我读到这个问题时,我的第一个问题跳到了智能匹配操作符
unless ( $input_day ~~ @days ) {
say "Smart Invalid Day";
}
所以我想知道使用grep是否比smart-match有好处,反之亦然。我知道smart match只在更高版本的Perl中可用,因此对于使用5.10.1之前的Perl版本的人来说,这并不是什么值得推荐的东西
我以前从来没有真正的标杆Perl代码,所以下面的代码是从一个在线示例编写的。我试着运行智能匹配示例200万次,运行grep示例200万次,并记录计时
use strict;
use warnings;
use v5.16.2;
use Benchmark;
my $input_day = shift;
my @days = qw /mon tue wed thu fri sat sun/;
my $smart_test_start = new Benchmark();
for(my $x=0; $x<10000000; $x++){
unless ( $input_day ~~ @days ) {
#here we would execute some code
}
}
my $smart_test_end = new Benchmark();
my $grep_test_start = new Benchmark();
for(my $y=0; $y<10000000; $y++){
if (!grep { $input_day eq $_ } @days ) {
#here we would execute some code
}
}
my $grep_test_end = new Benchmark();
my $smart_diff = timediff($smart_test_end, $smart_test_start);
my $grep_diff = timediff($grep_test_end, $grep_test_start);
say "SMART: ", timestr($smart_diff,'all');
say "GREP: ", timestr($grep_diff,'all');
输入“thu”
输入“sun”
输入“非”
在所有情况下,智能匹配操作符的性能似乎都优于grep。查看结果,我假设在早期用例中,这是因为智能匹配将在找到匹配后立即停止,而grep将在匹配第一次出现后继续检查数组的其余部分
然后我看到其他人建议使用某些模块来查找第一个实例等
人们不推荐智能匹配操作员有什么原因吗?智能匹配是否存在某些限制或不可靠性?请勿,重复请勿在生产代码中使用智能匹配运算符。根据smartmatch已标记为实验性: Smart match在v5.10.0中添加,并在v5.10.1中进行了重大修改,这一直是一个常见的投诉点。尽管有许多方法可以使用它,但对于Perl的用户和实现者来说,它也被证明是有问题和令人困惑的。关于如何最好地解决这一问题,已经提出了一些建议。很明显,smartmatch几乎肯定会在未来改变或消失。不建议依赖其当前行为 当解析器看到~~、给定或出现错误时,将发出警告。要禁用这些警告,可以将此行添加到适当的范围: 但是,请考虑替换这些功能的使用,因为它们可能会在变得稳定之前再次改变行为
这意味着,在这些问题得到解决之前,依赖于此功能的代码不能被视为稳定的。不要,重复不要在生产代码中使用smartmatch操作符。根据smartmatch已标记为实验性: Smart match在v5.10.0中添加,并在v5.10.1中进行了重大修改,这一直是一个常见的投诉点。尽管有许多方法可以使用它,但对于Perl的用户和实现者来说,它也被证明是有问题和令人困惑的。关于如何最好地解决这一问题,已经提出了一些建议。很明显,smartmatch几乎肯定会在未来改变或消失。不建议依赖其当前行为 当解析器看到~~、给定或出现错误时,将发出警告。要禁用这些警告,可以将此行添加到适当的范围: 但是,请考虑替换这些功能的使用,因为它们可能会在变得稳定之前再次改变行为
这意味着,在这些问题得到解决之前,依赖于此功能的代码不能被认为是稳定的。正确的解决方案是使用哈希而不是数组
my %days = map { $_ => 1 } @days
然后你就可以写了
unless ($days{$input_day}) {
say "Hash Invalid Day";
}
而且性能将远远超过任何其他解决方案
(我希望这是显而易见的,但是您应该只设置一次哈希,并在以后的所有测试中继续使用它。)正确的解决方案是使用哈希而不是数组
my %days = map { $_ => 1 } @days
然后你就可以写了
unless ($days{$input_day}) {
say "Hash Invalid Day";
}
而且性能将远远超过任何其他解决方案
(我希望这是显而易见的,但您应该只设置一次哈希,并在以后的所有测试中继续使用它。)希望添加我的经验,因为我做了一些测试。我一直使用Smart Match,最近厌倦了它会产生的警告 我有一个1亿的文本文件,10个字符串 Perl脚本将STDIN转换为数组,并使用3种常见方法查找数组中是否存在字符串。我尝试使用上面建议的哈希映射,但是哈希映射的生成时间是数组的3倍。如果您正在对现有值进行广泛的测试,那么在某一点上这种折衷可能是可行的,因为哈希上的exists检查基本上是即时的。它还将取决于您的数据源 在未来,我计划主要使用List::Util(any),因为它是一个核心模块,性能非常可靠
#!/usr/bin/perl
use List::Util qw(any);
my @arr = qw(a b c d e);
if ( any { $_ eq 'd' } @arr ) {
print "Found.\n";
}
方法:
List::Util (any): if ( any { $_ eq $a } @arr ) { do something. }
Perl Smartmatch: if ( $b ~~ @arr ) { do something. }
Grep: if ( grep { $c eq $_ } @arr ) { do something. }
我搜索了我知道存在于1,10100100010000100001000001000000001000000001000000001000000000位置的值。计时是通过Time::HiRes模块完成的
我发现,如果大多数值位于数组的开头,smartmatch将执行List::Utils方法。但是,如果你的值大部分在中间或结尾,或者不存在于数组列表中:Util将执行。grep似乎做了一次彻底的搜索,不管它是否找到了一个值
更多输出详细信息:
Smart Match total: 5.939 seconds.
List::Util::any: 7.332 seconds.
Grep total: 39.553 seconds.
阵列生成时间:30.315秒。
正在搜索100000000个arr元素。
任何搜索eavTa2eWr1
找到任何-eavTa2eWr1。
时间:0.540秒。
任何搜索mhEusMj5E7
任何发现-mhEusMj5E7。
时间:0.358秒。
任何搜索WGwHfJICK6
任何发现-WGWFJICK6。
时间:0.364秒。
任何搜索I48fNDYNKF
任何发现-I48fNDYNKF。
时间:0.359秒。
任何搜索q3YVBTmX9J
找到任何-q3YVBTmX9J。
时间:0.357秒。
任何搜索pw0J5vRCnW
任何发现-pw0J5vRCnW。
时间:0.358秒。
任何搜索GNJP5flX5z
找到任何-GNJP5flX5z。
时间:0.392秒。
任何搜索3
#!/usr/bin/perl
use List::Util qw(any);
my @arr = qw(a b c d e);
if ( any { $_ eq 'd' } @arr ) {
print "Found.\n";
}
List::Util (any): if ( any { $_ eq $a } @arr ) { do something. }
Perl Smartmatch: if ( $b ~~ @arr ) { do something. }
Grep: if ( grep { $c eq $_ } @arr ) { do something. }
Smart Match total: 5.939 seconds.
List::Util::any: 7.332 seconds.
Grep total: 39.553 seconds.
List::Util::any: 28.980 seconds.
Grep total: 34.790 seconds.
Smart Match total: 42.913 seconds.