регулярное выражение в то время как циклы - PullRequest
5 голосов
/ 05 июня 2011

При чтении этого SO сообщения - Существует ли версия JavaScript String.indexOf (), которая допускает регулярные выражения? ) Я размышляю, какая из следующих двух функций ищет последняя (самая большая) группа пробелов в 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 ]

2 голосов
/ 05 июня 2011
(function(str)
{   
    var result = /\s+(?!.*\s+)/.exec(str);
    return ((result)? result.index : -1);
})(txt);

сломан.Он будет соответствовать " \n", поскольку . не соответствует всем пробелам.В частности, он не соответствует пробелам "\r\n\u2028\u2029", которые соответствуют \s.

Если вы хотите найти хороший способ сопоставления с последней (самой большой) группой пробелов в txt, используйте RegExpниже с String.prototype.search:

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

Чтобы получить конечный индекс, вы не можете использовать свойство .lastIndex регулярного выражения, поскольку оно включает в себя часть \S*.Вы можете снова использовать .search.

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

Я думаю, какая из следующих двух функций, которые ищут последнюю (самую большую) группу пробелов в txt, работают быстрее (или они имеют незначительный запускразница во времени)

Для небольших строк результат, вероятно, незначителен независимо от того, какой (правильный) метод вы используете.Для больших строк итерация по всей строке будет дорогой, поэтому лучше всего использовать регулярное выражение, которое привязано в конце, то есть имеет $ в качестве последнего токена и не имеет ^ в нем,Интерпретатор может тратить время на поиск по всей строке, когда есть регулярное регулярное выражение, привязанное только к праву, но я полагаю, что большинство делает эту простую оптимизацию.

Это то, что я получаю на shellfree 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]

Наконец, вы должны знать, что \s не всегда означает одно и то же для всех переводчиков./\s/.test("\xA0"), который проверяет, является ли неразрывный пробел (думаю,  ) пробелом, ложным в IE 6, но верно в интерпретаторах большинства других браузеров (не уверен в IE 7 +).

1 голос
/ 05 июня 2011

Вы можете использовать jsPerf для сравнения производительности различных фрагментов JavaScript. Я создал тот, который использует ваши два варианта, и этот мной :

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

Он в основном разбивает строку в позиции совпадения, используя предварительное утверждение. Если совпадений не найдено, split возвращает массив только с одним элементом; в противном случае длина последней части вычитается из общей длины строки, чтобы получить индекс последнего соответствия.


Обновление Я немного подправил функции, и теперь у нас есть совершенно другие результаты по сравнению с предыдущим тестом . Теперь первая функция, которая теперь использует /\s+(?!\S+\s+)/ вместо /\s+(?!.*\s+)/, кажется самой быстрой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...