LoginSignup
0
0

Javascriptで最頻値を求めようとした備忘録

Last updated at Posted at 2024-04-21

※筆者はJavascript初学者

最頻値、厳密には「文字列が複数入った配列から、最も出現回数の多い文字列を返す」関数を作りたかった。
色々やり方はあると思うが、ちょっと躓いたところもあったのでメモしておく。

サンプルとした配列は下記。

main.js
let arr = ["melon","apple","apple","pine","apple","melon","orange"]

"apple"が3回、"melon"が2回、"orange"と"pine"が1回ずつ出現する。

参考

結論

読みやすい方

main.js
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を参考に、ちょっと書き方を改めてみた形。

短い方

main.js
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 ? (...) : nullcount >= countMax && (...)
  • input.mapinput.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のコンソール)
image.png
index=0の時のもので、xにはinitialValueで指定した[]があるわけなんだけど、コレはどこから来たのか……

0
0
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0