Быстрая группировка массива javascript

У меня есть массив из нескольких тысяч строк

['7/21/2011', '7/21/2011', '7/21/2011', '7/20/2011', etc]

В настоящее время я запускаю этот код для группировки по строке и получения максимального значения группы:

var max = 0;
var group = {};
arr.map(function (value) {
  if (group[value]) {
    group[value]++;
  } else {
    group[value] = 1;
  }
  max = Math.max(max, group[value]);
});

Есть ли улучшения, чтобы этот код работал быстрее?

EDIT: Результаты приведены в: http://jsperf.com/javascript-array-grouping2

EDIT EDIT: этот тест был ошибочным. Майк Самуэль был самым быстрым.

6000 записей test → http://jsperf.com/javascript-array-grouping2

Тест 10K записей → http://jsperf.com/javascript-array-grouping

Ответ 1

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

Вы также можете сделать тело своей функции быстрее, вырезая сравнение.

var max = 0;
var group = {};
for (var i = arr.length; --i >= 0;) {
  var value = arr[i];
  var n = group[value] = 1 - -(group[value] | 0);
  if (n > max) { max = n; }
}

Лучшее, что вам нужно сделать, это измерить браузеры, о которых вы заботитесь.

Ответ 2

Да, конечно. Я бы вычислил max последний, а не каждую итерацию, а не использовать if if:

var group = {};
arr.map(function (value) {
    group[value] = (group[value] || 0) + 1;
});

var max = 0;
for (key in group) {
    if (group[key] > max) max = group[key];
}

EDIT: Как Майк Самуэль говорит, что вы можете ускориться, используя индекс вместо карты:

var group = {};
var max = 0;

for (var i = arr.length; --i >= 0;) {
    group[value] = (group[value] || 0) + 1;
}
for (key in group) {
    if (group[key] > max) max = group[key];
}

Ответ 3

Я думаю, что на самом деле это зависит от механизма JS, на котором вы будете запускать этот код. Альтернатива, которую я считаю целесообразной, заключается в использовании

n = group[value] = (group[value]||0) + 1;
if (n > max) max = n;

для каждого элемента.

Я также думаю, что использование регулярного цикла может быть быстрее, потому что переменные, которые вы будете использовать, будут только локальными, а не закрытыми переменными закрытия (которые обычно медленнее), и вы также сохраните вызов функции за элемент. Обе эти проблемы не являются проблемами, если реализация может встроить это закрытие, но я не знаю, есть ли для них JS-реализации, достаточно умные для этого.