在$string
中给出两个字符串变量$needle
和perl
,检查$string
是否以$needle
开头的最有效方法是什么。
$string =~ /^\Q$needle\E/
是我能想到的最接近的匹配,它可以满足要求,但是我尝试的解决方案效率最低(到目前为止)。index($string, $needle) == 0
有效且对$string
和$needle
的某些值相对有效,但在其他位置不必要地搜索针头(如果在开始时未找到)。substr($string, 0, length($needle)) eq $needle
应该非常简单有效,但在我的几个测试中,大多数测试都不比前一个测试更有效。在perl
中是否有规范的方法可以做到这一点,我不会意识到或以任何方式优化上述任何解决方案?
(在我的特定用例中,$string
和$needle
在每次运行中都会有所不同,因此预编译regexp不是一种选择。)
如何衡量给定解决方案的性能的示例(此处来自POSIX sh
):
string='somewhat not so longish string' needle='somew'
time perl -e '
($n,$string,$needle) = @ARGV;
for ($i=0;$i<$n;$i++) {
index($string, $needle) == 0
}' 10000000 "$string" "$needle"
使用这些值,使用perl 5.14.2,index()
使用此系统的效果优于substr()+eq
,但使用:
string="aaaaabaaaaabaaaaabaaaaabaaaaabaaaaab" needle="aaaaaa"
那是相反的。
答案 0 :(得分:20)
这有多重要,真的吗?我做了很多基准测试,index
方法平均每次迭代0.68微秒;正则表达式方法1.14μs; substr
方法0.16μs。即使是我最糟糕的情况(2250-char字符串相等),index
需要2.4μs,正则表达式需要5.7μs,substr
需要0.5μs。
我的建议是编写一个库例程:
sub begins_with
{
return substr($_[0], 0, length($_[1])) eq $_[1];
}
并将优化工作重点放在其他地方。
更新:基于对我上面描述的“最坏情况”场景的批评,我运行了一组新的基准测试,其中包含一个20,000字符随机生成的字符串,将其与自身进行比较,并将字符串与最后一个字符串进行比较。字节。
对于如此长的字符串,正则表达式解决方案是迄今为止最差的(20,000字符正则表达式是地狱):匹配成功为105μs,匹配失败为100μs。
index
和substr
解决方案仍然非常快。成功/失败index
为11.83μs/11.86μs,substr
为4.09μs/4.15μs。将代码移动到单独的函数中添加约0.222±0.05μs。
基准代码位于:http://codepaste.net/2k1y8e
我不知道@Sphane数据的特征,但我的建议是。
答案 1 :(得分:2)
另一种选择是将rindex
的位置设置为0,这意味着“从位置<= 0开始,在$ str中获取$ substr的索引”,即它仅检查$ substr是否为$的前缀str:
> rindex "abc", "a", 0
0
> rindex "abc", "b", 0
-1