Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

regex vs while loops

While reading this SO post - Is there a version of JavaScript's String.indexOf() that allows for regular expressions?) I ponder which of the following two functions that look for the last (largest) whitespace group in txt run faster (or do they have negligible run-time difference)

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

or

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

Briefly, the first uses a regex expression to look for a whitespace group that is not followed by any other whitespace groups, and the second uses a while loop.

Any help with this matter is much appreciated.

like image 639
knight Avatar asked Oct 10 '22 20:10

knight


1 Answers

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

is broken. It will match " \n" because . does not match all space characters. Specifically it does not match the space characters "\r\n\u2028\u2029" which are matched by \s.

If you want a good way to match the last (largest) whitespace group in txt, use the RegExp below with String.prototype.search:

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

To get the end index, you can't use the .lastIndex property of the regular expression since it includes the \S* portion. You can use .search again though.

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

I ponder which of the following two functions that look for the last (largest) whitespace group in txt run faster (or do they have negligible run-time difference)

For small strings the result is likely negligible no matter what (correct) method you use. For large strings, iterating over the whole string is going to be expensive, so your best bet is to use a regular expression that is anchored at the end, i.e. has $ as the last token and does not have ^ in it. An interpreter can waste time doing a full string search when there is a right-only-anchored regex, but I believe most do this simple optimization.

This is what I get on squarefree shell under chrome.

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]

Finally, you should be aware that \s does not always mean the same thing on all interpreters. /\s/.test("\xA0") which tests whether the non-breaking space (think  ) is a space is false on IE 6 but true on most other browsers' interpreters (not sure about IE 7+).

like image 177
Mike Samuel Avatar answered Oct 20 '22 06:10

Mike Samuel