◆ ハッシュ使うと配列を毎回走査しなくていい

普段は書きやすさ優先で配列の intersect (両方の配列にある要素を取り出す)をするときに
function intersect(a, b){
return b.filter(e => a.includes(e))
}
と書いています

ですが これだと b の数だけ a に入っているかを探すので 実際はかなりの無駄な処理があります
b の要素がひとつも a に入っていなくて b が 1000 個の要素なら 1000 回も a の配列を最初から最後まで確認することになります

こういう ライブラリにおいておきそうな いろいろなところで使う関数はできれば高速にしておきたいです

プリミティブ値しか考慮してないですが こういうのを作ってみました
function intersect2(a, b){
var m = {}
a.forEach(e => m[e] = 1)
return b.filter(e => m[e])
}

配列を全部みないで ハッシュによる計算 1 回だけでいいです

速度比較してみます
var r = _ => ~~(Math.random() * 10000)

var a = Array.from(Array(5000), r)
var b = Array.from(Array(5000), r)


function i1(a, b){
return b.filter(e => a.includes(e))
}

function i2(a, b){
var m = {}
a.forEach(e => m[e] = 1)
return b.filter(e => m[e])
}

console.time("1")
console.log(1, i1(a,b).length)
console.timeEnd("1")

console.time("2")
console.log(2, i2(a,b).length)
console.timeEnd("2")

///

console.time("1")
console.log(1, i1(a,b).length)
console.timeEnd("1")

console.time("2")
console.log(2, i2(a,b).length)
console.timeEnd("2")

///

console.time("1")
console.log(1, i1(a,b).length)
console.timeEnd("1")

console.time("2")
console.log(2, i2(a,b).length)
console.timeEnd("2")
1 1960
1: 363.264ms
2 1960
2: 2.262ms
1 1960
1: 346.083ms
2 1960
2: 2.441ms
1 1960
1: 349.202ms
2 1960
2: 1.766ms

0~9999 までの数字でランダムに 5000 個ずつ A と B に入れて intersect してます
個数はどっちも 1960 で動きはあっているはずです

速度をみると 350ms くらいと 2ms くらい
すごい差!

プリミティブ値しかできないですが オブジェクトを Map に置き換えればちょっと速度は落ちますが オブジェクトに対しても使えるようになります
IE ではムリですけど
polyfill で Map 使えるようにしても内部ではハッシュにならないので速度はむしろ遅いような気がします
まぁ IE だけを遅くしてユーザが自分から Chrome などに移ってくれるように仕向けるのはありかもしれないですけど


でも 関数型の言語って遅い例の filter するだけみたいなシンプルに書く(そうしか書けない?)イメージがありますが 速度面はあまりよくないのかな