※筆者はJavascript初学者
最頻値、厳密には「文字列が複数入った配列から、最も出現回数の多い文字列を返す」関数を作りたかった。
色々やり方はあると思うが、ちょっと躓いたところもあったのでメモしておく。
サンプルとした配列は下記。
let arr = ["melon","apple","apple","pine","apple","melon","orange"]
"apple"が3回、"melon"が2回、"orange"と"pine"が1回ずつ出現する。
参考
- JavaScriptの配列の最頻値を求めるコピペ
- javascript 配列の最頻値を求める
- (↑の解説記事) JavaScript 自由研究 - 最頻値を求めるコード - カメリアの記事
- SIMPLE STATISTICS …統計分野向けライブラリ
結論
読みやすい方
function mode(input){
let index = new Map
let countMax = 0
let output
input.forEach(value =>{
let count = -~index.get(value)
count ? count++ : count = 1;
index.set(value,count);
count >= countMax && (output = value,countMax = count);// 後から来た方を残す
});
return output
}
※複数結果がある場合、元の配列でindexが大きい方を残す
SIMPLE STATISTICSのmodeFastを参考に、ちょっと書き方を改めてみた形。
短い方
const c = (x, i, v) => (x[i] ? x[i].add(v) : x[i] = new Set([v]), i);
const result = arr.reduce(function (x, v) { return (this.set(v, c(x, (this.get(v) + 1 || 1), v)), x); }.bind(new Map), []).pop();
console.log([...result]);
※すべての結果を配列に入れる
javascript 配列の最頻値を求めるの微改造
訂正:2024/05/05
-
count >= countMax ? (...) : null
⇒count >= countMax && (...)
-
input.map
⇒input.forEach
@mashuel 様、@juner 様よりご指摘いただきました。ありがとうございました。
躓いたとこ
['a','p','l','e']
javascript 配列の最頻値を求めるのコードをそのまま使った場合、['a','p','l','e']
が出力結果になってしまった。
これはc
のうちSet(v)
で作られたもので、これがそのまま残ってしまうためである。
文字列を相手にする場合はSet([v])
にしてやればよい。
reduceのaccumulatorがわからない
上記でやりたいことができることは実験してわかったので、使う上ではこれでいいんだけど、理解ができていないところがある。
勉強のため、arr.sort().reduce(function (x, v, i) {
とreturn ...
の間にconsole.log(x)
を入れて、accumulatorの中身を見てみたら、画像のようなのが見られた。(Chromeのコンソール)
index=0の時のもので、xにはinitialValueで指定した[]があるわけなんだけど、コレはどこから来たのか……