Идиоматически найти количество вхождений, которое данное значение имеет в массиве
У меня есть массив с повторяющимися значениями. Я хотел бы найти количество вхождений для любого заданного значения.
Например, если у меня есть массив, определяемый так: var dataset = [2,2,4,2,6,4,7,8];
, я хочу найти количество вхождений определенного значения в массиве. То есть программа должна показать, что если у меня есть 3 вхождения значения 2
, 1 вхождение значения 6
и т.д.
Какой самый идиоматический/элегантный способ сделать это?
Ответы
Ответ 1
reduce
данном случае более подходящим является reduce
чем filter
поскольку он не создает временный массив только для подсчета.
var dataset = [2,2,4,2,6,4,7,8];
var search = 2;
var count = dataset.reduce(function(n, val) {
return n + (val === search);
}, 0);
console.log(count);
Ответ 2
Новые браузеры только благодаря использованию Array.filter
var dataset = [2,2,4,2,6,4,7,8];
var search = 2;
var occurrences = dataset.filter(function(val) {
return val === search;
}).length;
console.log(occurrences); // 3
Ответ 3
array.filter(c => c === searchvalue).length;
Ответ 4
Вот один из способов сразу показать ВСЕ:
var dataset = [2, 2, 4, 2, 6, 4, 7, 8];
var counts = {}, i, value;
for (i = 0; i < dataset.length; i++) {
value = dataset[i];
if (typeof counts[value] === "undefined") {
counts[value] = 1;
} else {
counts[value]++;
}
}
console.log(counts);
// Object {
// 2: 3,
// 4: 2,
// 6: 1,
// 7: 1,
// 8: 1
//}
Ответ 5
Используя обычный цикл, вы можете найти вхождения последовательно и надежно:
const dataset = [2,2,4,2,6,4,7,8];
function getNumMatches(array, valToFind) {
let numMatches = 0;
for (let i = 0, j = array.length; i < j; i += 1) {
if (array[i] === valToFind) {
numMatches += 1;
}
}
return numMatches;
}
alert(getNumMatches(dataset, 2)); // should alert 3
ДЕМО: https://jsfiddle.net/a7q9k4uu/
Чтобы сделать его более универсальным, функция может принять функцию предиката с пользовательской логикой (возвращающей true
/false
), которая будет определять окончательное число. Например:
const dataset = [2,2,4,2,6,4,7,8];
function getNumMatches(array, predicate) {
let numMatches = 0;
for (let i = 0, j = array.length; i < j; i += 1) {
const current = array[i];
if (predicate(current) === true) {
numMatches += 1;
}
}
return numMatches;
}
const numFound = getNumMatches(dataset, (item) => {
return item === 2;
});
alert(numFound); // should alert 3
ДЕМО: https://jsfiddle.net/57en9nar/1/
Ответ 6
var dataset = [2,2,4,2,6,4,7,8], count = {}
dataset.forEach(function(el){
count[el] = count[el] + 1 || 1
});
console.log(count)
// {
// 2: 3,
// 4: 2,
// 6: 1,
// 7: 1,
// 8: 1
// }
Ответ 7
Вы можете использовать метод array.reduce(callback[, initialValue])
в JavaScript 1.8
var dataset = [2,2,4,2,6,4,7,8],
dataWithCount = dataset.reduce( function( o , v ) {
if ( ! o[ v ] ) {
o[ v ] = 1 ;
} else {
o[ v ] = o[ v ] + 1;
}
return o ;
}, {} );
// print data with count.
for( var i in dataWithCount ){
console.log( i + 'occured ' + dataWithCount[i] + 'times ' );
}
// find one number
var search = 2,
count = dataWithCount[ search ] || 0;
Ответ 8
Вы можете подсчитать все элементы в массиве в одной строке, используя сокращение.
[].reduce((a,b) => (a[b] = a[b] + 1 || 1) && a, {})
Это даст объект, ключи которого являются отдельными элементами в массиве, а значения - это количество вхождений элементов в массиве. Затем вы можете получить доступ к одному или нескольким подсчетам, обратившись к соответствующему ключу на объекте.
Например, если вы должны были обернуть это в функции с именем count()
:
function count(arr) {
return arr.reduce((a,b) => (a[b] = a[b] + 1 || 1) && a, {})
}
count(['example']) // { example: 1 }
count([2,2,4,2,6,4,7,8])[2] // 3
Ответ 9
Я нашел более полезным получить список объектов с ключом для подсчета и ключом для подсчета:
const data = [2,2,4,2,6,4,7,8]
let counted = []
for (var c of data) {
const alreadyCounted = counted.map(c => c.name)
if (alreadyCounted.includes(c)) {
counted[alreadyCounted.indexOf(c)].count += 1
} else {
counted.push({ 'name': c, 'count': 1})
}
}
console.log(counted)
который возвращает:
[ { name: 2, count: 3 },
{ name: 4, count: 2 },
{ name: 6, count: 1 },
{ name: 7, count: 1 },
{ name: 8, count: 1 } ]
Это не самый чистый метод, и если кто - нибудь знает, как достичь того же результата с reduce
, дайте мне знать. Тем не менее, он дает результат, с которым довольно легко работать.
Ответ 10
Во-первых, вы можете использовать решение Brute Force Solution, перейдя к линейному поиску.
public int LinearSearchcount(int[] A, int data){
int count=0;
for(int i=0;i<A.length;i++) {
if(A[i]==data) count++;
}
return count;
}
Однако для этого мы получаем сложность по времени как O (n). Но с помощью бинарного поиска мы можем улучшить нашу сложность.