配列からの重複削除
JavaScript で、配列から重複した要素をとりのぞく処理は以下のように書ける(検索すると、たくさんヒットする)。
const unique = array => array.filter((value, index, self) => self.indexOf(value) === index);
これは次のように使う:
> unique([1, 3, 2, 1, 3]) => [1, 3, 2]
手続き的な処理の解説
unique に渡す引数配列 array を、関数 `(value, index, array) => array.indexOf(value) === index` で filter する。
つまり value, index, array の三引数をとり、これで array.indexOf(value) === index を評価して、 true になる要素 value を残して配列として返す。
先の例につかった配列 `[1, 3, 2, 1, 3]` を例につかう。
filter は配列の先頭から順に値を渡してくれる。
- 最初の要素の値は 1、このインデックスは 0、配列は [1, 3, 2, 1, 3]。
- 次の要素の値は 3、インデックス 1、配列は [1, 3, 2, 1, 3]。
この調子で、入力配列を filter に順次渡される三つ組の配列として表現すると、以下のようになる。:
[(1, 0, [1,3,2,1,3]), (3, 1, [1,3,2,1,3]), (2, 2, [1,3,2,1,3]), (1, 3, [1,3,2,1,3]), (3, 4, [1,3,2,1,3])]
これを順次 `array.indexOf(value) === index` で評価すると、:
[true, true, true, false, false]
というのは、最初の要素を例にとれば以下のように評価が進むため。:
((value, index, array) => array.indexOf(value) === index))(1, 0, [1,3,2,1,3]); => [1,3,2,1,3].indexOf(1) === 0 => 0 === 0 => true
結果、先頭から順に `[1, 3, 2]` が取り出されて終わる。
オーダー
array に対する二重ループだから array の長さを n として O(n^2)。
filter に渡す関数の、その引数に array たる self がバインドされること、そして関数本体で array を self.indexOf() として使っているため。(ワーストケースは、重複がない配列への適用)