Считать уникальные элементы массива без сортировки
В JavaScript следующие элементы найдут количество элементов в массиве. Предполагая, что в массиве
должно быть не менее одного элемента,
arr = ["jam", "beef", "cream", "jam"]
arr.sort();
var count = 1;
var results = "";
for (var i = 0; i < arr.length; i++)
{
if (arr[i] == arr[i+1])
{
count +=1;
}
else
{
results += arr[i] + " --> " + count + " times\n" ;
count=1;
}
}
Можно ли это сделать без использования sort() или без мутирования массива? Я бы предположил, что массив нужно будет заново создать, а затем сортировка может быть выполнена на вновь созданном массиве, но я хочу знать, что лучший способ без сортировки.
И да, я художник, а не программист, ваша честь.
Ответы
Ответ 1
Быстрый способ сделать это - скопировать уникальные элементы в объект.
var counts = {};
for (var i = 0; i < arr.length; i++) {
counts[arr[i]] = 1 + (counts[arr[i]] || 0);
}
Когда этот цикл будет завершен, объект counts
будет иметь счет каждого отдельного элемента массива.
Ответ 2
Быстрый способ сделать это с помощью new Set()
объекта.
Наборы являются удивительными, и мы должны использовать их чаще. Они быстрые и поддерживаются Chrome, Firefox, Microsoft Edge и node.js.
- Что быстрее Set или Object? от Andrei Kashcha
Элементы в Set
всегда будут уникальными, поскольку он хранит только одну копию каждого введенного значения. Здесь используется функция, которая использует это свойство:
function countUnique(iterable) {
return new Set(iterable).size;
}
console.log(countUnique('banana')); //=> 3
console.log(countUnique([5,6,5,6])); //=> 2
console.log(countUnique([window, document, window])); //=> 2
Ответ 3
Почему не что-то вроде:
var arr = ["jam", "beef", "cream", "jam"]
var uniqs = arr.reduce((acc, val) => {
acc[val] = acc[val] === undefined ? 1 : acc[val] += 1;
return acc;
}, {});
console.log(uniqs)
Ответ 4
Это выражение дает вам все уникальные элементы массива без его мутации:
arr.filter(function(v,i) { return i==arr.lastIndexOf(v); })
Вы можете связать это выражение с этим выражением, чтобы построить строку результатов без сортировки:
.forEach(function(v) {
results+=v+" --> " + arr.filter(function(w){return w==v;}).length + " times\n";
});
В первом случае фильтр принимает только последний из каждого конкретного элемента; во втором случае фильтр включает в себя все элементы этого типа, а .length
- счетчик.
Ответ 5
То же, что это решение, но меньше кода.
let counts = {};
arr.forEach(el => counts[el] = 1 + (counts[el] || 0))