Underscore.js: найти наиболее часто встречающееся значение в массиве?
Рассмотрим следующий простой массив:
var foods = ['hotdog', 'hamburger', 'soup', 'sandwich', 'hotdog', 'watermelon', 'hotdog'];
С underscore
существует ли функция или комбинация функций, которые я могу использовать для выбора наиболее часто встречающегося значения (в данном случае это hotdog
)?
Ответы
Ответ 1
_.chain(foods).countBy().pairs().max(_.last).head().value()
countBy: Сортирует список в группы и возвращает количество для количества объектов в каждой группе.
pairs: Преобразуйте объект в список пар [key, value]
.
max: Возвращает максимальное значение в списке. Если предоставляется функция итератора, она будет использоваться для каждого значения для генерации критерия, по которому оценивается значение.
last: Возвращает последний элемент массива
head: Возвращает первый элемент массива
chain: Возвращает обернутый объект. Методы вызова для этого объекта будут продолжать возвращать завернутые объекты до тех пор, пока не будет использовано значение.
value: Извлекает значение обернутого объекта.
Ответ 2
Вы можете сделать это за один проход, используя _.reduce
. Основная идея состоит в том, чтобы отслеживать частоты слов и наиболее распространенное слово одновременно:
var o = _(foods).reduce(function(o, s) {
o.freq[s] = (o.freq[s] || 0) + 1;
if(!o.freq[o.most] || o.freq[s] > o.freq[o.most])
o.most = s;
return o;
}, { freq: { }, most: '' });
Это оставляет 'hotdot'
в o.most
.
Демо: http://jsfiddle.net/ambiguous/G9W4m/
Вы также можете сделать это с помощью each
(или даже простого цикла for
), если вы не против предварительного кэширования кеша переменная:
var o = { freq: { }, most: '' };
_(foods).each(function(s) {
o.freq[s] = (o.freq[s] || 0) + 1;
if(!o.freq[o.most] || o.freq[s] > o.freq[o.most])
o.most = s;
});
Демо: http://jsfiddle.net/ambiguous/WvXEV/
Вы также можете разбить o
на две части и использовать слегка измененную версию выше, тогда вам не нужно было бы говорить o.most
, чтобы получить 'hotdog'
.