正则表达式与while循环

时间:2011-06-05 14:37:35

标签: javascript regex performance

在阅读此SO post - Is there a version of JavaScript's String.indexOf() that allows for regular expressions?)时,我会思考以下哪两个函数寻找txt中最后一个(最大)的空白组运行速度更快(或者它们是否可以忽略不计)运行时间差异)

(function(str)
{   
    var result = /\s+(?!.*\s+)/.exec(str);
    return ((result)? result.index : -1);
})(txt);

(function(str)
{
   var regex = /\s+/g;
   var result;
   var index = -1;
   while(result = regex.exec(str))
   {
       index = result.index;
   }
   return index;
})(txt);

简而言之,第一个使用正则表达式来查找没有任何其他空格组的空白组,第二个使用while循环。

非常感谢任何有关此事的帮助。

2 个答案:

答案 0 :(得分:2)

(function(str)
{   
    var result = /\s+(?!.*\s+)/.exec(str);
    return ((result)? result.index : -1);
})(txt);

坏了。它将与" \n"匹配,因为.与所有空格字符都不匹配。具体而言,它与"\r\n\u2028\u2029"匹配的空格字符\s不匹配。

如果您想要一个匹配txt中最后一个(最大)空白组的好方法,请使用下面的RegExpString.prototype.search

var indexOfStartOfLastWhitespaceGroup = str.search(/\s+\S*$/);

要获取结束索引,您不能使用正则表达式的.lastIndex属性,因为它包含\S*部分。您可以再次使用.search

if (indexOfStartOfLastWhitespaceGroup >= 0) {
  var indexOfEndOfLastWhitespaceGroup = str.search(/\S*$/);
  ...
}
  

我认为在txt中寻找最后一个(最大)空白组的以下两个函数中的哪一个运行得更快(或者它们的运行时差异可以忽略不计)

对于小字符串,无论您使用何种(正确)方法,结果都可能忽略不计。对于大字符串,迭代整个字符串将是昂贵的,所以最好的办法是使用一个锚定在最后的正则表达式,即$作为最后一个标记,并且没有{{1 }} 在里面。当有一个只有正确锚定的正则表达式时,解释器可以浪费时间进行完整的字符串搜索,但我相信大多数人都会进行这种简单的优化。

这是我在chrome squarefree shell下获得的内容。

^

最后,您应该意识到var s = ''; for (var i = 10000; --i >= 0;) s += 'abba'; s += 'foo'; var t0 = Date.now(); for (var i = 100; --i >= 0;) /foo$/.test(s); var t1 = Date.now(); var t2 = Date.now(); for (var i = 100; --i >= 0;) /abbafoo/.test(s); var t3 = Date.now(); [t1 - t0, t3 - t2] // emits [1, 8] 并不总是对所有口译员都意味着同样的事情。在IE 6上测试非中断空间(想象\s)是否为空的/\s/.test("\xA0")是假的,但在大多数其他浏览器的解释器上都是如此(不确定IE 7 +)。

答案 1 :(得分:1)

您可以使用jsPerf来比较不同JavaScript代码段的效果。我创建了one that uses your two variants and this one by me

function(str) {
    var parts = str.split(/(?=\s+)/);
    return parts.length === 1 ? -1 : str.length - parts[parts.length-1].length;
}

它基本上使用前瞻断言将字符串拆分到匹配位置。如果未找到匹配项,split将返回仅包含一个项目的数组;否则从字符串的总长度中减去最后一部分的长度,以获得最后一次匹配的索引。


更新我稍微调整了一些功能,现在我们与results相比有了一些完全不同的previous benchmark。现在,第一个使用/\s+(?!\S+\s+)/代替/\s+(?!.*\s+)/的函数似乎是最快的。