配列内の重複する値を削除して、ユニークな値だけで配列を構成する方法をまとめました。
オブジェクトを使用して重複を削除
function deleteDuplicate1(arr) { var result = {}; arr.forEach(function(v) { result[v+ '::' + typeof v] = v; }); return Object.keys(result).map(function(v){ return result[v]; }); }
まずはオブジェクトを使った方法(deleteDuplicate1)です。
新たなオブジェクトresultを宣言し、キーに「配列の値と型の文字列」を指定して値を格納しています。重複した値(と型)がある場合には、新しいキーは作られずに値は上書きされます。
Object.keys(result)は、resultが持つキー情報を配列で返します。mapメソッドと組み合わせることで、キー情報に対するオブジェクトの値を返しています。
配列を使用して重複を削除
function deleteDuplicate2(arr) { var result = []; for (var i=0, l=arr.length; i<l; i++){ if (!~result.indexOf(arr[i])){ result.push(arr[i]); } } return result; }
次に配列を使った方法(deleteDuplicate2)です。
indexOf()を使って配列resultにすでに同じ値が格納されていないか?を判定し、格納されていない場合に配列resultに値を追加します。
※ indexOf()は指定した値が配列内にあればその位置、なければ”-1″を返します。チルダ演算子(~)を用いると、”-1″は”0″, それ以外は非0の数値に変換(整数のビット反転)されるので、booleanのように扱うことができます。
filter関数を使用して重複を削除
filter()は配列から条件に一致した値を抽出して、新たな配列を作成する関数です。
function deleteDuplicate3(arr) { return arr.filter( function(value,index,self){ return self.indexOf(value) === index; } ); }
この場合、indexOf()が返す値と、配列のインデックスが一致したものが抽出されます。
indexOf()は指定された値が最初に現れたインデックスを返すので、以後重複した値に対してはfalseと判定されて値は追加されません。
Setオブジェクトを使用して重複を削除
ES6からの機能になりますが、Setオブジェクトを使うと非常にシンプルに処理を記述することができます。
function deleteDuplicate4(arr) { return Array.from(new Set(arr)); }
処理速度を比較する。
以上4つの方法を紹介しましたが、コードのシンプルさだけではなく、処理速度はどうなのか?も気になるところです。
試しに10000個のランダムな文字列を持つ配列に対して、処理速度を比較しました。
deleteDuplicate1(); // 43.865966796875ms deleteDuplicate2(); // 2767.873046875ms deleteDuplicate3(); // 4793.097900390625ms deleteDuplicate4(); // 19.97705078125ms
処理速度でいうとdeleteDuplicate4()の「Setオブジェクトを使って重複を削除する」方法が一番速いことがわかります。
ただし、SetオブジェクトはES6からの機能です。ES6をサポートできない環境であれば、deleteDuplicate1()の「オブジェクトを使って重複を削除する」方法が処理の速い方法となりますね。