Respostas:
Muito simples:
var count = 0;
for(var i = 0; i < array.length; ++i){
if(array[i] == 2)
count++;
}
const count = countItems(array, 2);e os detalhes da implementação podem ser discutidos por dentro.
[ esta resposta é um pouco datada: leia as edições ]
Diga olá aos seus amigos: mape filtere reducee forEache everyetc.
(Ocasionalmente, apenas escrevo for-loops em javascript, devido à falta de escopo no nível do bloco; portanto, você precisa usar uma função como corpo do loop de qualquer maneira, se precisar capturar ou clonar seu índice ou valor de iteração. geralmente são mais eficientes, mas às vezes você precisa de um fechamento.)
A maneira mais legível:
[....].filter(x => x==2).length
(Poderíamos ter escrito .filter(function(x){return x==2}).length)
A seguir, é mais eficiente em termos de espaço (O (1) em vez de O (N)), mas não tenho certeza de quanto benefício / penalidade você pode pagar em termos de tempo (não mais que um fator constante desde a sua visita) cada elemento exatamente uma vez):
[....].reduce((total,x) => (x==2 ? total+1 : total), 0)
(Se você precisar otimizar esse trecho de código específico, um loop for pode ser mais rápido em alguns navegadores ... você pode testar as coisas em jsperf.com.)
Você pode ser elegante e transformá-lo em uma função de protótipo:
[1, 2, 3, 5, 2, 8, 9, 2].count(2)
Como isso:
Object.defineProperties(Array.prototype, {
count: {
value: function(value) {
return this.filter(x => x==value).length;
}
}
});
Você também pode usar a técnica antiga de loop for regular (consulte outras respostas) dentro da definição de propriedade acima (novamente, isso provavelmente seria muito mais rápido).
2017 editar :
Opa, essa resposta ficou mais popular que a resposta correta. Na verdade, basta usar a resposta aceita. Embora essa resposta possa ser engraçada, os compiladores js provavelmente não otimizam (ou não podem devido à especificação) desses casos. Então você realmente deve escrever um loop for simples:
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;
}
}
});
Você pode definir uma versão .countStrictEq(...)que use a ===noção de igualdade. A noção de igualdade pode ser importante para o que você está fazendo! (por exemplo [1,10,3,'10'].count(10)==2, porque números como '4' == 4 em javascript ... portanto, chamá-lo .countEqou .countNonstrictenfatizar que ele usa o ==operador.)
Considere também usar sua própria estrutura de dados multiset (por exemplo, como a de python ' collections.Counter') para evitar ter que fazer a contagem em primeiro lugar.
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 {}
}
}
Demo:
> 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)
Nota: No entanto, se você ainda deseja a maneira de programação funcional (ou uma linha descartável descartável sem substituir o Array.prototype), você pode escrevê-la com mais facilidade hoje em dia como [...].filter(x => x==2).length. Se você se preocupa com o desempenho, observe que, embora este seja assintoticamente o mesmo desempenho que o loop for (O (N) time), ele pode exigir O (N) memória extra (em vez da memória O (1)), porque quase certamente gere uma matriz intermediária e conte os elementos dessa matriz intermediária.
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. Em seguida, use-o chamando count(list)where list é uma matriz de números. Você também pode fazer const count = (list) => list.filter((x) => x.someProp === 'crazyValue').lengthpara contar instâncias de crazyValue na matriz de objetos. Observe que é uma correspondência exata para a propriedade.
Atualização do ES6 para JS:
Observe que você sempre deve usar iguais a triplos: ===para obter uma comparação correta:
// 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
A seguinte função Arrow unânime (função lambda) em JS:
(x) => {
const k = 2
return k * x
}
pode ser simplificado para este formulário conciso para uma única entrada:
x => 2 * x
onde o returnestá implícito.
2017: se alguém ainda estiver interessado na pergunta, minha solução é a seguinte:
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);
Se você estiver usando lodash ou sublinhado, o método _.countBy fornecerá um objeto de totais agregados codificados por cada valor na matriz. Você pode transformar isso em uma linha só se precisar contar apenas um valor:
_.countBy(['foo', 'foo', 'bar'])['foo']; // 2
Isso também funciona bem em matrizes de números. O one-liner para o seu exemplo seria:
_.countBy([1, 2, 3, 5, 2, 8, 9, 2])[2]; // 3
A maneira mais estranha de pensar em fazer isso é:
(a.length-(' '+a.join(' ')+' ').split(' '+n+' ').join(' ').match(/ /g).length)+1
Onde:
Minha sugestão, use um tempo ou para loop ;-)
Não usar um laço normalmente significa entregar o processo ao longo de algum método que não usar um loop.
Aqui está uma maneira do nosso codificador odiador de loop satisfazer o seu ódio, a um preço:
var a=[1, 2, 3, 5, 2, 8, 9, 2];
alert(String(a).replace(/[^2]+/g,'').length);
/* returned value: (Number)
3
*/
Você também pode chamar indexOf repetidamente, se estiver disponível como método de matriz, e mover o ponteiro da pesquisa a cada vez.
Isso não cria uma nova matriz, e o loop é mais rápido que um forEach ou filtro.
Pode fazer a diferença se você tiver um milhão de membros para olhar.
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- embora tenha cuidado com isso ou sua implementação não funcionará bem com dois dígitos.
A maioria das soluções postadas usando funções de matriz, como filtro, estão incompletas porque não são parametrizadas.
Aqui está uma solução com a qual o elemento a ser contado pode ser definido em tempo de execução.
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);
A vantagem dessa abordagem é que poderia facilmente mudar a função para contar, por exemplo, o número de elementos maiores que X.
Você também pode declarar a função de redução embutida
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) ...é mais difícil de ler e não oferece vantagem sobre apenas ... (acc, x) => acc += number == 2.... Eu gosto do seu uso em +=vez de no acc + (number == 2)entanto. Parece uma sintaxe injustificada HACK.
Realmente, por que você precisaria mapou filterpara isso?
reducenasceu "para este tipo de operações:
[1, 2, 3, 5, 2, 8, 9, 2].reduce( (count,2)=>count+(item==val), 0);
é isso aí! (se item==valem cada iteração, 1 será adicionado ao acumulador count, conforme trueserá resolvido em 1).
Como uma função:
function countInArray(arr, val) {
return arr.reduce((count,item)=>count+(item==val),0)
}
Ou vá em frente e estenda suas matrizes:
Array.prototype.count = function(val) {
return this.reduce((count,item)=>count+(item==val),0)
}
É melhor envolvê-lo em função:
let countNumber = (array,specificNumber) => {
return array.filter(n => n == specificNumber).length
}
countNumber([1,2,3,4,5],3) // returns 1
Aqui está uma maneira do ES2017 + de obter as contagens para todos os itens da matriz em 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;
});
Você também pode, opcionalmente, classificar a saída:
const countsSorted = Object.entries(counts).sort(([_, a], [__, b]) => a - b);
console.log (countsSorted) para sua matriz de exemplo:
[
[ '2', 3 ],
[ '1', 1 ],
[ '3', 1 ],
[ '5', 1 ],
[ '8', 1 ],
[ '9', 1 ]
]
Eu acredito que o que você está procurando é uma abordagem funcional
const arr = ['a', 'a', 'b', 'g', 'a', 'e'];
const count = arr.filter(elem => elem === 'a').length;
console.log(count); // Prints 3
elem === 'a' é a condição, substitua-a por sua.
count = arr.filter(elem => elem === 'a').lengthoucount = arr.filter(elem => {return elem === 'a'}).length
Eu sou um fã iniciante da função de redução do array js.
const myArray =[1, 2, 3, 5, 2, 8, 9, 2];
const count = myArray.reduce((count, num) => num === 2 ? count + 1 : count, 0)
De fato, se você realmente deseja ter uma fantasia, pode criar uma função de contagem no protótipo Array. Então você pode reutilizá-lo.
Array.prototype.count = function(filterMethod) {
return this.reduce((count, item) => filterMethod(item)? count + 1 : count, 0);
}
Então faça
const myArray =[1, 2, 3, 5, 2, 8, 9, 2]
const count = myArray.count(x => x==2)
Solução por recursão
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, reduceou uma simples forLoope também mais cara quando se olha para o desempenho, mas ainda é uma ótima maneira de fazê-lo com recursão. Minha única mudança é: acho que seria melhor criar uma função e adicionar um filtro dentro dela para copiar a matriz e evitar uma mutação da matriz original, depois use a recursiva como uma função interna.
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');
}
Eu faria algo assim:
var arrayCount = [1,2,3,4,5,6,7,8];
function countarr(){
var dd = 0;
arrayCount.forEach( function(s){
dd++;
});
console.log(dd);
}
Crie um novo método para a classe Array no arquivo de nível principal e use-o em todo o seu projeto.
// say in app.js
Array.prototype.occurrence = function(val) {
return this.filter(e => e === val).length;
}
Use isso em qualquer lugar do seu projeto -
[1, 2, 4, 5, 2, 7, 2, 9].occurrence(2);
// above line returns 3
Aqui está um liner em javascript.
(v === 2)na matriz, retornando uma matriz de uns e zeros.[1, 2, 3, 5, 2, 8, 9, 2]
.map(function(v) {
return v === 2 ? 1 : 0;
})
.reduce((a, b) => a + b, 0);
O resultado é 3.
Dependendo de como você deseja executá-lo:
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, …}
Você pode usar a propriedade length na matriz JavaScript:
var myarray = [];
var count = myarray.length;//return 0
myarray = [1,2];
count = myarray.length;//return 2