回答:
非常にシンプル:
var count = 0;
for(var i = 0; i < array.length; ++i){
if(array[i] == 2)
count++;
}
const count = countItems(array, 2);おり、実装の詳細は内部で議論することができます。
[ この答えは少し日付が古い:編集を読む ]
友達に挨拶する:mapand filterand reduceand forEachand everyetc.
(ブロックレベルのスコープが欠落しているため、JavaScriptでたまにforループを書くだけなので、反復インデックスまたは値をキャプチャまたは複製する必要がある場合は、とにかく関数をループの本体として使用する必要があります。Forループ一般的にはより効率的ですが、場合によってはクロージャーが必要になります。)
最も読みやすい方法:
[....].filter(x => x==2).length
(.filter(function(x){return x==2}).length代わりに書くこともできました)
以下はよりスペース効率が良い(O(N)ではなくO(1))ですが、時間に関してどの程度のメリット/ペナルティを支払うことができるかはわかりません(アクセスしてから一定の係数を超えないでください)各要素を1回だけ):
[....].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ループテクニック(他の回答を参照)を挿入することもできます(ここでも、はるかに高速です)。
2017編集:
おっと、この答えは正解よりも人気が高まっています。実際には、受け入れられた答えを使用してください。この答えはかわいいかもしれませんが、jsコンパイラーはおそらくそのようなケースを最適化しません(または仕様のために最適化できません)。だからあなたは本当に単純なforループを書くべきです:
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、JavaScriptの「4」== 4のような数値...それを呼び出す.countEqか.countNonstrict、==演算子を使用することを強調します。)
またcollections.Counter、最初にカウントを行う必要がないように、独自のマルチセットデータ構造(たとえば、pythonの ' 'のような)を使用することも検討してください。
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)
補足:ただし、関数型プログラミングの方法(またはArray.prototypeをオーバーライドせずに使い捨てのワンライナー)が必要な場合は、最近ではもっと簡潔に記述できます[...].filter(x => x==2).length。パフォーマンスを重視する場合、これはfor-loop(O(N)時間)と漸近的に同じパフォーマンスですが、ほぼO(1)メモリではなくO(N)メモリが必要になる場合があることに注意してください。確かに中間配列を生成し、その中間配列の要素を数えます。
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のインスタンスをカウントすることもできます。これは、プロパティと完全に一致していることに注意してください。
JSへのES6の更新:
===正しい比較を得るためには、常に三重の等号を使用する必要があることに注意してください。
// 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
次のJSの全会一致のArrow関数(ラムダ関数):
(x) => {
const k = 2
return k * x
}
単一の入力に対して、この簡潔な形式に簡略化できます。
x => 2 * x
どこをreturn暗示しています。
ループを使用しないと、通常、いくつかの方法を介してプロセスを渡す意味ないループを使用します。
これは、私たちのループ嫌いコーダーが彼の嫌悪感を代償として満たすことができる方法です:
var a=[1, 2, 3, 5, 2, 8, 9, 2];
alert(String(a).replace(/[^2]+/g,'').length);
/* returned value: (Number)
3
*/
配列メソッドとして使用できる場合は、indexOfを繰り返し呼び出して、毎回検索ポインターを移動することもできます。
これは新しい配列を作成せず、ループはforEachまたはフィルターよりも高速です。
100万人のメンバーを見ると、違いが出る可能性があります。
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より大きい要素の数をカウントするように関数を簡単に変更できることです。
インラインでreduce関数を宣言することもできます
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配列のreduce関数の初心者です。
const myArray =[1, 2, 3, 5, 2, 8, 9, 2];
const count = myArray.reduce((count, num) => num === 2 ? count + 1 : count, 0)
実際、もしあなたが本当に凝りたいのであれば、Arrayプロトタイプにcount関数を作成できます。その後、それを再利用できます。
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);
}
実行方法に応じて:
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, …}
JavaScript配列でlengthプロパティを使用できます:
var myarray = [];
var count = myarray.length;//return 0
myarray = [1,2];
count = myarray.length;//return 2