То, что вы хотите достичь, это карта частот. Во-первых, вы можете построить карту частот. Используя значение в массиве в качестве ключа, вы можете легко увеличить счетчик на карте.
Начальное значение для любого вновь добавленного ключа: ((freq[val] || 0) + 1)
. Это просто означает, получить последнее значение или 0 и увеличить на 1.
Получив карту, вы можете преобразовать ее в массив пар имя / количество.
let arr = ["red", "red", "green", "red", "green", "blue"];
let frequencyMap = arr.reduce((freq, val) => {
return { ...freq, [val]: ((freq[val] || 0) + 1) }
}, {});
let results = Object.keys(frequencyMap).map(key => {
return { name : key, count : frequencyMap[key] }
});
console.log(results);
.as-console-wrapper { top: 0; max-height: 100% !important; }
Код Golf
Это однострочник с функцией отображения. :)
const freqArray = (a, fn) => ((f) => Object.keys(f).map(k => fn(k, f[k])))(a.reduce((m, v) => ({ ...m, [v]: ((m[v] || 0) + 1) }), {}));
let arr = [ "red", "red", "green", "red", "green", "blue" ];
let freq = freqArray(arr, (k, v) => ({ name : k, count : v }));
console.log(freq);
.as-console-wrapper { top: 0; max-height: 100% !important; }
Сортировка результатов
Вы также можете отсортировать результаты по имени, но если вы это сделаете (так как ключи уникальны) сортировать по количеству не нужно, потому что имена будут уникальными.
const freqArray = (arr, opts) => ((freq) => Object.keys(freq).map(key => opts.mapFn(key, freq[key])))(arr.reduce((m, v) => ({ ...m, [v]: ((m[v] || 0) + 1) }), {})).sort(opts.cmpFn);
let arr = [ "red", "red", "green", "red", "green", "blue" ];
let freq = freqArray(arr, {
mapFn : (key, val) => ({ name : key, count : val }),
cmpFn : (a, b) => a.name.localeCompare(b.name) || (a.count - b.count)
});
console.log(freq);
.as-console-wrapper { top: 0; max-height: 100% !important; }
Вы можете отменить условие сортировки для сортировки по количеству (des c), а затем по имени:
const freqArray = (arr, opts) => ((freq) => Object.keys(freq).map(key => opts.mapFn(key, freq[key])))(arr.reduce((m, v) => ({ ...m, [v]: ((m[v] || 0) + 1) }), {})).sort(opts.cmpFn);
let arr = [ "red", "red", "green", "red", "green", "blue", "green", "blue", "blue" ];
let freq = freqArray(arr, {
mapFn : (key, val) => ({ name : key, count : val }),
cmpFn : (a, b) => (b.count - a.count) || a.name.localeCompare(b.name)
});
console.log(freq);
.as-console-wrapper { top: 0; max-height: 100% !important; }