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
(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+).
You can use jsPerf to compare the performance of different JavaScript snippets. I’ve created 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;
}
It basically splits the string at the position of the match using a look-ahead assertion. If no match is found, split
returns an array with just one item; otherwise the length of the last part is subtracted from the total length of the string to get the index of the last match.
Update I’ve tweaked the functions a little bit and now we’ve got some completely different results compared to the previous benchmark. Now the first function that is now using /\s+(?!\S+\s+)/
instead of /\s+(?!.*\s+)/
seems to be the fastest.