Array.includesと Set.has の速度比較をした。


Array.includesとSet.hasで速度差がどれぐらい出るかを調べた。
良くあるObjectの添字を使ったテクニック等とも比較。


```js

const { performance } = require('perf_hooks');

const test = (len=100) => {

    const targetLen = Math.floor(len /10)

    const  shuffle = (a) => {
        const c = [...a]
        for (let i = c.length - 1; i > 0; i--) {
            const j = Math.floor(Math.random() * (i + 1));
            [c[i], c[j]] = [c[j], c[i]]
        }
        return c
    }

    const spec = [
        ["nodeのバージョン",process.versions.node],
        ["配列のサイズ" , len ],
        ["検索する項目数" , targetLen ]
    ]


    //配列をlen個作成する [0,1,2,3,4,...,len-1]
    const base = Array.from({length: len}, (v, k) => k)

    //シャッフルする
    const ary = shuffle(base)

    //Set化する
    const set =(() => {
        const start = performance.now()
        const set = new Set(ary)
        const end =  performance.now()
        spec.push([ "Setの生成時間" , end - start])
        return set
    })()

    //Mapの生成
    const map = (() => {
        const pre = base.map(b => [b,b])
        const start = performance.now()
        const map = new Map(pre)
        const end = performance.now()
        spec.push([ "Mapの生成時間" , end - start ])
        return map
    })()

    //数字を添え字にしたオブジェクトを作る {"0":0,"1":1,...,[len-1]:len-1}
    const obj = (() => {
        const start = performance.now()
        const obj = ary.reduce((pre,cur) => {
            pre[`${cur}`] = cur
            return pre
        }, {})

        const end = performance.now()
        spec.push([ "Objectの生成時間" , end - start ])

        return obj
    })() 



console.log(`

${spec.map(r => r.join("|")).join("\n")}

`)


    //存在チェックの試験用の配列
    const target = shuffle(base).slice(0,targetLen)

    const result = [
        ["含むチェックの方式","処理時間時間"],
    ]



    //indexOf を使う
    {
        const start = performance.now();
        for(let t of target ){
            if(ary.indexOf(t) > -1){

            }
        }
        const end = performance.now();

        result.push([ "Array.indexOf" , end - start])
    }


    //Array.inclueds のテスト
    {
        const start = performance.now();
        for(let t of target ){
            if(ary.includes(t)){

            }
        }
        const end = performance.now();

        result.push([ "Array.inclueds" , end - start])
    }

    //Set.has のテスト
    {
        const start = performance.now();
        for(let t of target ){
            if(set.has(t)){

            }
        }
        const end = performance.now();    
        result.push([ "Set.has" , end - start])
    }


    //Map.has のテスト
    {
        const start = performance.now();
        for(let t of target ){
            if(map.has(t)){

            }
        }
        const end = performance.now();    
        result.push([ "Map.has" , end - start])
    }


    //オブジェクトの key を使ったテクニック のテスト

    {
        const start = performance.now();
        for(let t of target ){
            if(obj[t]){

            }
        }
        const end = performance.now();    
        result.push([ "obj[t]" , end - start])
    }


    // in でも試してみる

    {

        const start = performance.now();
        for(let t of target ){
            if( t in obj){

            }
        }
        const end = performance.now();    
        result.push([ "t in obj" , end - start])

    }


console.log(`

${result.map(r => r.join("|")).join("\n")}

`)

    

}

test(100000)

```

### 1回目

項目|値
:--|:--
nodeのバージョン|12.18.1
配列のサイズ|100000
検索する項目数|10000
Setの生成時間|8.558184027671814
Mapの生成時間|13.922562003135681
Objectの生成時間|31.00487995147705



チェックの方式|処理時間時間
:--|:--
Array.indexOf|944.757071018219
Array.inclueds|944.7714960575104
Set.has|2.41020405292511
Map.has|2.5640859603881836
obj[t]|1.2104129791259766
t in obj|0.7970190048217773


### 2回目

項目|値
:--|:--
nodeのバージョン|12.18.1
配列のサイズ|100000
検索する項目数|10000
Setの生成時間|8.59699296951294
Mapの生成時間|11.606724977493286
Objectの生成時間|35.41410505771637




チェックの方式|処理時間時間
:--|:--
Array.indexOf|945.146420955658
Array.inclueds|945.0419319868088
Set.has|2.4140039682388306
Map.has|2.5660550594329834
obj[t]|1.2223680019378662
t in obj|0.8045949935913086

# 3回目

項目|値
:--|:--
nodeのバージョン|12.18.1
配列のサイズ|100000
検索する項目数|10000
Setの生成時間|8.761895060539246
Mapの生成時間|11.589484095573425
Objectの生成時間|30.759024024009705

チェックの方式|処理時間時間
:--|:--
Array.indexOf|943.3850150108337
Array.inclueds|947.2091970443726
Set.has|2.461833953857422
Map.has|2.6097559928894043
obj[t]|1.2358649969100952
t in obj|0.8159409761428833

### 結論 Setを使う。

結果的だけみると in 演算子を使うパターンが一番早いが object に一旦変換するテクニックは
生成コストが高く常に使って効果を得られるようなテクニックではないので使わないほうが良い。

また、存在チェックしたい物が stringやnumber以外の場合は使えない。

Setは生成コストはそれほど高くなく、検索も早いので、状況によっては含むチェックのためだけに 配列から一旦Setを生成する価値はありそう。

Set.has と Map.hasはスピードにあまり差が無い。（MapがSetに依存してるのかな？

indexof と includes は速度に差は無く順当に遅い

あまり不思議な点はなかった。

ちなみに Map の key が オブジェクトでも良いって最近知った。