Risposte:
Molto semplice:
var count = 0;
for(var i = 0; i < array.length; ++i){
if(array[i] == 2)
count++;
}
const count = countItems(array, 2);e i dettagli di implementazione possono essere discussi all'interno.
[ questa risposta è un po 'datata: leggi le modifiche ]
Saluta i tuoi amici: mape filterereduce e forEache everyecc
(Scrivo solo occasionalmente for-loops in javascript, a causa della mancanza di scoping a livello di blocco, quindi devi usare una funzione come corpo del loop comunque se devi catturare o clonare il tuo indice o valore di iterazione. For-loops sono generalmente più efficienti, ma a volte è necessaria una chiusura.)
Il modo più leggibile:
[....].filter(x => x==2).length
(Avremmo potuto .filter(function(x){return x==2}).lengthinvece scrivere )
Quanto segue è più efficiente in termini di spazio (O (1) anziché O (N)), ma non sono sicuro di quanto beneficio / penalità potresti pagare in termini di tempo (non più di un fattore costante da quando visiti ogni elemento esattamente una volta):
[....].reduce((total,x) => (x==2 ? total+1 : total), 0)
(Se hai bisogno di ottimizzare questo particolare pezzo di codice, un ciclo for potrebbe essere più veloce su alcuni browser ... puoi testare le cose su jsperf.com.)
Puoi quindi essere elegante e trasformarlo in una funzione prototipo:
[1, 2, 3, 5, 2, 8, 9, 2].count(2)
Come questo:
Object.defineProperties(Array.prototype, {
count: {
value: function(value) {
return this.filter(x => x==value).length;
}
}
});
Puoi anche applicare la vecchia tecnica for-loop (vedi altre risposte) all'interno della definizione della proprietà sopra (di nuovo, probabilmente sarebbe molto più veloce).
Modifica 2017 :
Spiacenti, questa risposta è diventata più popolare della risposta corretta. In realtà, basta usare la risposta accettata. Sebbene questa risposta possa essere carina, i compilatori js probabilmente non ottimizzano (o non possono a causa delle specifiche) tali casi. Quindi dovresti davvero scrivere un semplice ciclo:
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;
}
}
});
È possibile definire una versione .countStrictEq(...)che utilizza la ===nozione di uguaglianza. La nozione di uguaglianza può essere importante per quello che stai facendo! (ad esempio [1,10,3,'10'].count(10)==2, perché numeri come '4' == 4 in javascript ... quindi chiamandolo .countEqo .countNonstrictsottolinea che usa il== operatore.)
Considera anche di usare la tua struttura di dati multiset (ad esempio come quella di Python ' collections.Counter') per evitare di dover fare il conteggio in primo luogo.
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)
sidenote: Tuttavia, se volevi ancora la modalità di programmazione funzionale (o un one-liner usa e getta senza sovrascrivere Array.prototype), oggi potresti scriverlo in maniera più concisa come [...].filter(x => x==2).length. Se ti preoccupi delle prestazioni, nota che mentre questa è asintoticamente la stessa performance del tempo for-loop (O (N)), potrebbe richiedere O (N) memoria aggiuntiva (invece di O (1) memoria) perché quasi certamente genera un array intermedio e quindi conta gli elementi di tale array intermedio.
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. Quindi usalo chiamando count(list)dove list è un array di numeri. Puoi anche fare il const count = (list) => list.filter((x) => x.someProp === 'crazyValue').lengthconteggio delle istanze di crazyValue nella matrice di oggetti. Nota, è una corrispondenza esatta per la proprietà.
Aggiornamento ES6 a JS:
Nota che dovresti sempre usare triple egals: ===per ottenere un confronto corretto:
// 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
La seguente funzione freccia unanime (funzione lambda) in JS:
(x) => {
const k = 2
return k * x
}
può essere semplificato in questa forma concisa per un singolo input:
x => 2 * x
dove returnè implicito.
2017: se qualcuno è ancora interessato alla domanda, la mia soluzione è la seguente:
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 si utilizza lodash o il carattere di sottolineatura, il metodo _.countBy fornirà un oggetto di totali aggregati digitato da ciascun valore dell'array. Puoi trasformarlo in una riga unica se devi contare solo un valore:
_.countBy(['foo', 'foo', 'bar'])['foo']; // 2
Questo funziona bene anche su matrici di numeri. Il one-liner per il tuo esempio sarebbe:
_.countBy([1, 2, 3, 5, 2, 8, 9, 2])[2]; // 3
Il modo più strano che posso pensare di fare questo è:
(a.length-(' '+a.join(' ')+' ').split(' '+n+' ').join(' ').match(/ /g).length)+1
Dove:
Il mio consiglio, usa un po 'o per il ciclo ;-)
Non usare un ciclo di solito significa consegnare il processo ad un metodo che lo fa utilizza un ciclo.
Ecco un modo in cui il nostro programmatore che odia i loop può soddisfare il suo odio, ad un prezzo:
var a=[1, 2, 3, 5, 2, 8, 9, 2];
alert(String(a).replace(/[^2]+/g,'').length);
/* returned value: (Number)
3
*/
Puoi anche chiamare ripetutamente indexOf, se è disponibile come metodo array, e spostare il puntatore di ricerca ogni volta.
Ciò non crea un nuovo array e il ciclo è più veloce di un forEach o di un filtro.
Potrebbe fare la differenza se hai un milione di membri da guardare.
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- anche se fai attenzione o la tua implementazione non funzionerà bene con le doppie cifre.
La maggior parte delle soluzioni pubblicate che utilizzano funzioni di array come il filtro sono incomplete perché non sono parametrizzate.
Ecco una soluzione con la quale l'elemento da contare può essere impostato in fase di esecuzione.
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);
Il vantaggio di questo approccio è che potrebbe facilmente cambiare la funzione per contare, ad esempio, il numero di elementi maggiore di X.
Puoi anche dichiarare la funzione di riduzione in linea
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) ...è più difficile da leggere e non offre alcun vantaggio rispetto al solo ... (acc, x) => acc += number == 2.... Mi piace il tuo uso +=invece che acc + (number == 2)però. Sembra però una sintassi ingiustificata HACK.
Davvero, perché avresti bisogno mapo filterper questo?
reduceè "nato" per questo tipo di operazioni:
[1, 2, 3, 5, 2, 8, 9, 2].reduce( (count,2)=>count+(item==val), 0);
questo è tutto! (se item==valin ogni iterazione, allora 1 verrà aggiunto all'accumulatore count, come truerisolverà a 1).
Come una funzione:
function countInArray(arr, val) {
return arr.reduce((count,item)=>count+(item==val),0)
}
Oppure, vai avanti ed estendi le tue matrici:
Array.prototype.count = function(val) {
return this.reduce((count,item)=>count+(item==val),0)
}
È meglio avvolgerlo in funzione:
let countNumber = (array,specificNumber) => {
return array.filter(n => n == specificNumber).length
}
countNumber([1,2,3,4,5],3) // returns 1
Ecco un modo ES2017 + per ottenere i conteggi per tutti gli elementi dell'array in 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;
});
È inoltre possibile ordinare l'output facoltativamente:
const countsSorted = Object.entries(counts).sort(([_, a], [__, b]) => a - b);
console.log (countSorted) per il tuo array di esempio:
[
[ '2', 3 ],
[ '1', 1 ],
[ '3', 1 ],
[ '5', 1 ],
[ '8', 1 ],
[ '9', 1 ]
]
Credo che quello che stai cercando sia un approccio funzionale
const arr = ['a', 'a', 'b', 'g', 'a', 'e'];
const count = arr.filter(elem => elem === 'a').length;
console.log(count); // Prints 3
elem === 'a' è la condizione, sostituiscila con la tua.
count = arr.filter(elem => elem === 'a').lengthocount = arr.filter(elem => {return elem === 'a'}).length
Sono un fan iniziale della funzione di riduzione di js array.
const myArray =[1, 2, 3, 5, 2, 8, 9, 2];
const count = myArray.reduce((count, num) => num === 2 ? count + 1 : count, 0)
In effetti, se vuoi davvero fantasticare, puoi creare una funzione di conteggio sul prototipo di array. Quindi puoi riutilizzarlo.
Array.prototype.count = function(filterMethod) {
return this.reduce((count, item) => filterMethod(item)? count + 1 : count, 0);
}
Quindi fa
const myArray =[1, 2, 3, 5, 2, 8, 9, 2]
const count = myArray.count(x => x==2)
Soluzione per ricorsione
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, reduceo un semplice forLoop, e anche, più costoso quando si guarda alle prestazioni, ma è comunque un ottimo modo di farlo con la ricorsione. La mia unica modifica è: penso solo che sarebbe meglio creare una funzione e aggiungere un filtro al suo interno per copiare l'array ed evitare una mutazione dell'array originale, quindi utilizzare il ricorsivo come funzione 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');
}
Vorrei fare qualcosa del genere:
var arrayCount = [1,2,3,4,5,6,7,8];
function countarr(){
var dd = 0;
arrayCount.forEach( function(s){
dd++;
});
console.log(dd);
}
Crea un nuovo metodo per la classe Array nel file di livello principale e usalo in tutto il tuo progetto.
// say in app.js
Array.prototype.occurrence = function(val) {
return this.filter(e => e === val).length;
}
Usalo ovunque nel tuo progetto -
[1, 2, 4, 5, 2, 7, 2, 9].occurrence(2);
// above line returns 3
Ecco una riga in javascript.
(v === 2) nell'array, restituendo un array di uno e zero.[1, 2, 3, 5, 2, 8, 9, 2]
.map(function(v) {
return v === 2 ? 1 : 0;
})
.reduce((a, b) => a + b, 0);
Il risultato è 3.
A seconda di come si desidera eseguirlo:
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, …}
È possibile utilizzare la proprietà length nell'array JavaScript:
var myarray = [];
var count = myarray.length;//return 0
myarray = [1,2];
count = myarray.length;//return 2