Ответы:
Очень просто:
var count = 0;
for(var i = 0; i < array.length; ++i){
if(array[i] == 2)
count++;
}
const count = countItems(array, 2);детали реализации можно обсуждать внутри.
[ этот ответ немного устарел: читайте правки ]
Передай привет своим друзьям: mapи filterи reduceи forEachи everyт. Д.
(Я только иногда пишу for-loop в javascript, поскольку отсутствует область видимости на уровне блоков, поэтому вам все равно придется использовать функцию в качестве тела цикла, если вам нужно захватить или клонировать ваш итерационный индекс или значение. For-loops в целом более эффективны, но иногда требуется закрытие.)
Самый читаемый способ:
[....].filter(x => x==2).length
(Мы могли бы написать .filter(function(x){return x==2}).lengthвместо)
Ниже приведено более эффективное использование пространства (O (1), а не O (N)), но я не уверен, сколько из выгоды / штрафа вы могли бы заплатить с точки зрения времени (не более чем постоянный фактор, так как вы посещаете каждый элемент ровно один раз):
[....].reduce((total,x) => (x==2 ? total+1 : total), 0)
(Если вам нужно оптимизировать этот конкретный фрагмент кода, цикл for может быть быстрее в некоторых браузерах ... вы можете протестировать его на jsperf.com.)
Затем вы можете быть элегантным и превратить его в функцию-прототип:
[1, 2, 3, 5, 2, 8, 9, 2].count(2)
Как это:
Object.defineProperties(Array.prototype, {
count: {
value: function(value) {
return this.filter(x => x==value).length;
}
}
});
Вы также можете вставить обычный старый метод for-loop (см. Другие ответы) в приведенное выше определение свойства (опять же, это, вероятно, будет намного быстрее).
2017 редактировать :
К сожалению, этот ответ стал более популярным, чем правильный ответ. На самом деле, просто используйте принятый ответ. Хотя этот ответ может быть симпатичным, компиляторы js, вероятно, не (или не могут из-за спецификации) оптимизировать такие случаи. Таким образом, вы должны написать простой цикл:
Object.defineProperties(Array.prototype, {
count: {
value: function(query) {
/*
Counts number of occurrences of query in array, an integer >= 0
Uses the javascript == notion of equality.
*/
var count = 0;
for(let i=0; i<this.length; i++)
if (this[i]==query)
count++;
return count;
}
}
});
Вы можете определить версию, в .countStrictEq(...)которой используется ===понятие равенства. Понятие равенства может быть важно для того, что вы делаете! (например [1,10,3,'10'].count(10)==2, потому что числа типа «4» == 4 в javascript ... следовательно, вызывая его .countEqили .countNonstrictподчеркивая, он использует ==оператор.)
Также рассмотрите возможность использования вашей собственной многосетевой структуры данных (например, типа «питона collections.Counter»), чтобы избежать необходимости делать подсчет в первую очередь.
class Multiset extends Map {
constructor(...args) {
super(...args);
}
add(elem) {
if (!this.has(elem))
this.set(elem, 1);
else
this.set(elem, this.get(elem)+1);
}
remove(elem) {
var count = this.has(elem) ? this.get(elem) : 0;
if (count>1) {
this.set(elem, count-1);
} else if (count==1) {
this.delete(elem);
} else if (count==0)
throw `tried to remove element ${elem} of type ${typeof elem} from Multiset, but does not exist in Multiset (count is 0 and cannot go negative)`;
// alternatively do nothing {}
}
}
Демо-версия:
> counts = new Multiset([['a',1],['b',3]])
Map(2) {"a" => 1, "b" => 3}
> counts.add('c')
> counts
Map(3) {"a" => 1, "b" => 3, "c" => 1}
> counts.remove('a')
> counts
Map(2) {"b" => 3, "c" => 1}
> counts.remove('a')
Uncaught tried to remove element a of type string from Multiset, but does not exist in Multiset (count is 0 and cannot go negative)
sidenote: Хотя, если вы все еще хотите использовать функциональное программирование (или одноразовую однострочную компоновку без переопределения Array.prototype), вы можете написать ее более кратко в наши дни как [...].filter(x => x==2).length. Если вы заботитесь о производительности, обратите внимание, что, хотя это асимптотически та же производительность, что и цикл for (O (N) время), может потребоваться O (N) дополнительная память (вместо O (1) памяти), поскольку она почти конечно, создайте промежуточный массив и затем посчитайте элементы этого промежуточного массива.
array.reduce(function(total,x){return x==value? : total+1 : total}, 0)
[...].reduce(function(total,x){return x==2 ? total+1 : total}, 0)
const count = (list) => list.filter((x) => x == 2).length. Затем используйте его, позвонив, count(list)где list это массив чисел. Вы также const count = (list) => list.filter((x) => x.someProp === 'crazyValue').lengthможете подсчитать количество экземпляров crazyValue в массиве объектов. Обратите внимание, это точное соответствие для свойства.
ES6 Обновление до JS:
Обратите внимание, что вы всегда должны использовать тройные равенства: ===чтобы получить правильное сравнение:
// Let has local scope
let array = [1, 2, 3, 5, 2, 8, 9, 2]
// Functional filter with an Arrow function
array.filter(x => x === 2).length // -> 3
Следующая единственная функция Arrow (лямбда-функция) в JS:
(x) => {
const k = 2
return k * x
}
может быть упрощено до этой краткой формы для одного ввода:
x => 2 * x
где returnподразумевается.
2017: Если кто-то все еще интересуется этим вопросом, мое решение заключается в следующем:
const arrayToCount = [1, 2, 3, 5, 2, 8, 9, 2];
const result = arrayToCount.filter(i => i === 2).length;
console.log('number of the found elements: ' + result);
Если вы используете lodash или подчеркивание, то метод _.countBy предоставит объект совокупных итогов, определяемый каждым значением в массиве. Вы можете превратить это в однострочник, если вам нужно только посчитать одно значение:
_.countBy(['foo', 'foo', 'bar'])['foo']; // 2
Это также хорошо работает на массивах чисел. Однострочником для вашего примера будет:
_.countBy([1, 2, 3, 5, 2, 8, 9, 2])[2]; // 3
Отсутствие цикла обычно означает передачу процесса какому-либо методу, который использует цикл.
Вот способ, которым наш кодовый ненавидящий кодер может удовлетворить его отвращение по цене:
var a=[1, 2, 3, 5, 2, 8, 9, 2];
alert(String(a).replace(/[^2]+/g,'').length);
/* returned value: (Number)
3
*/
Вы также можете повторно вызывать indexOf, если он доступен как метод массива, и каждый раз перемещать указатель поиска.
Это не создает новый массив, и цикл выполняется быстрее, чем forEach или фильтр.
Это может иметь значение, если у вас есть миллион членов, чтобы посмотреть.
function countItems(arr, what){
var count= 0, i;
while((i= arr.indexOf(what, i))!= -1){
++count;
++i;
}
return count
}
countItems(a,2)
/* returned value: (Number)
3
*/
String(a).match(/2/g).length + 1- хотя остерегайтесь этого, иначе ваша реализация не будет хорошо работать с двузначными числами.
Большинство опубликованных решений, использующих функции массива, такие как фильтр, являются неполными, поскольку они не параметризованы.
Здесь идет решение, с помощью которого элемент для подсчета может быть установлен во время выполнения.
function elementsCount(elementToFind, total, number){
return total += number==elementToFind;
}
var ar = [1, 2, 3, 5, 2, 8, 9, 2];
var elementToFind=2;
var result = ar.reduce(elementsCount.bind(this, elementToFind), 0);
Преимущество этого подхода заключается в том, что он может легко изменить функцию, чтобы подсчитать, например, количество элементов больше X.
Вы также можете объявить функцию приведения встроенной
var ar = [1, 2, 3, 5, 2, 8, 9, 2];
var elementToFind=2;
var result = ar.reduce(function (elementToFind, total, number){
return total += number==elementToFind;
}.bind(this, elementToFind), 0);
var elementToFind=2; ... function (elementToFind, total, number){ return total += number==elementToFind; }.bind(this, elementToFind) ...труднее читать и не дает никаких преимуществ по сравнению с просто ... (acc, x) => acc += number == 2.... Мне нравится ваше использование +=вместо, acc + (number == 2)хотя. Похоже, необоснованный синтаксис HACK, хотя.
Действительно, зачем тебе это mapили filterдля этого?
reduceбыл «рожден» для таких операций:
[1, 2, 3, 5, 2, 8, 9, 2].reduce( (count,2)=>count+(item==val), 0);
Это оно! (если item==valв каждой итерации к аккумулятору будет добавлено 1 count, как trueбудет разрешено 1).
Как функция:
function countInArray(arr, val) {
return arr.reduce((count,item)=>count+(item==val),0)
}
Или продолжайте расширять свои массивы:
Array.prototype.count = function(val) {
return this.reduce((count,item)=>count+(item==val),0)
}
Лучше обернуть это в функцию:
let countNumber = (array,specificNumber) => {
return array.filter(n => n == specificNumber).length
}
countNumber([1,2,3,4,5],3) // returns 1
Вот ES2017 + способ получить количество для всех элементов массива в O (N):
const arr = [1, 2, 3, 5, 2, 8, 9, 2];
const counts = {};
arr.forEach((el) => {
counts[el] = counts[el] ? (counts[el] += 1) : 1;
});
Вы также можете при желании отсортировать вывод:
const countsSorted = Object.entries(counts).sort(([_, a], [__, b]) => a - b);
console.log (countsSorted) для вашего примера массива:
[
[ '2', 3 ],
[ '1', 1 ],
[ '3', 1 ],
[ '5', 1 ],
[ '8', 1 ],
[ '9', 1 ]
]
Я считаю, что вы ищете, это функциональный подход
const arr = ['a', 'a', 'b', 'g', 'a', 'e'];
const count = arr.filter(elem => elem === 'a').length;
console.log(count); // Prints 3
elem === 'a' - это условие, замените его своим.
count = arr.filter(elem => elem === 'a').lengthилиcount = arr.filter(elem => {return elem === 'a'}).length
Я начинающий фанат функции снижения массива js.
const myArray =[1, 2, 3, 5, 2, 8, 9, 2];
const count = myArray.reduce((count, num) => num === 2 ? count + 1 : count, 0)
На самом деле, если вы действительно хотите проявить фантазию, вы можете создать функцию count для прототипа Array. Тогда вы можете использовать его повторно.
Array.prototype.count = function(filterMethod) {
return this.reduce((count, item) => filterMethod(item)? count + 1 : count, 0);
}
Тогда делай
const myArray =[1, 2, 3, 5, 2, 8, 9, 2]
const count = myArray.count(x => x==2)
Решение рекурсией
function count(arr, value) {
if (arr.length === 1) {
return arr[0] === value ? 1 : 0;
} else {
return (arr.shift() === value ? 1 : 0) + count(arr, value);
}
}
count([1,2,2,3,4,5,2], 2); // 3
filter, reduceили простой forLoop, а также более дорогой, если смотреть на производительность, но все же отличный способ сделать это с помощью рекурсии. Мое единственное изменение: я просто думаю, что было бы лучше создать функцию и добавить в нее фильтр, чтобы скопировать массив и избежать мутации исходного массива, а затем использовать рекурсив в качестве внутренней функции.
var arrayCount = [1,2,3,2,5,6,2,8];
var co = 0;
function findElement(){
arrayCount.find(function(value, index) {
if(value == 2)
co++;
});
console.log( 'found' + ' ' + co + ' element with value 2');
}
Я бы сделал что-то подобное:
var arrayCount = [1,2,3,4,5,6,7,8];
function countarr(){
var dd = 0;
arrayCount.forEach( function(s){
dd++;
});
console.log(dd);
}
Создайте новый метод для класса Array в файле уровня ядра и используйте его во всем проекте.
// say in app.js
Array.prototype.occurrence = function(val) {
return this.filter(e => e === val).length;
}
Используйте это где угодно в вашем проекте -
[1, 2, 4, 5, 2, 7, 2, 9].occurrence(2);
// above line returns 3
Вот один вкладыш в JavaScript.
(v === 2)в массиве, возвращая массив единиц и нулей.[1, 2, 3, 5, 2, 8, 9, 2]
.map(function(v) {
return v === 2 ? 1 : 0;
})
.reduce((a, b) => a + b, 0);
Результат есть 3.
В зависимости от того, как вы хотите его запустить:
const reduced = (array, val) => { // self explanatory
return array.filter((element) => element === val).length;
}
console.log(reduced([1, 2, 3, 5, 2, 8, 9, 2], 2));
// 3
const reducer = (array) => { // array to set > set.forEach > map.set
const count = new Map();
const values = new Set(array);
values.forEach((element)=> {
count.set(element, array.filter((arrayElement) => arrayElement === element).length);
});
return count;
}
console.log(reducer([1, 2, 3, 5, 2, 8, 9, 2]));
// Map(6) {1 => 1, 2 => 3, 3 => 1, 5 => 1, 8 => 1, …}
Вы можете использовать свойство length в массиве JavaScript:
var myarray = [];
var count = myarray.length;//return 0
myarray = [1,2];
count = myarray.length;//return 2