Tips

JavaScriptで重複チェック、重複削除をする方法

  • このエントリーをはてなブックマークに追加

JavaScriptでデータの重複チェックと重複削除ができることをご存知でしょうか?

基本的な文法だけを使うとforEachを複雑にした方法があるのですが、自分としては使いづらいなと思っているので他の方法でシンプルなものを紹介します。

また動画でも解説しているので併せてどうぞ。

JavaScriptで簡単に重複削除する方法

まず重複削除について一番シンプルな方法があるので紹介します。

const number = ["a", "b", "b", "c", "c", "d"];

const set = new Set(number);
console.log(set); // {"a","b","c","d"}と出力される

forEachを使うより簡単な方法としてSetを使う方法があります。

Setは関数ではなくオブジェクトでして、オブジェクトの新規生成(new Set)の引数に重複削除したいものを配列として入れると自動的に重複削除したオブジェクトを作成してくれます。

JavaScriptで重複チェックをする方法

続いて重複しているものを抽出したい時にはfilter関数を使うのがシンプルです。

const number = ["a", "b", "b", "c", "c", "d"];
const result = number.filter((val, i, arr) => {
  return arr.indexOf(val) != i;
});
console.log(result); // ["b","c"]が出力される

filter関数は別の記事でも解説しているのですが、繰り返し処理で特定の条件に合うものを配列で返してくれます。

filterの詳しい解説は以下の記事も参考にしてください。

先ほどのコードは初学者の方だとパッと見ただけで何をしているのか分からないかもしれないので、細かく説明していきます。

filter関数の引数の3つについては、val(1個ずつの要素)、i(要素のインデックス番号)、arry(配列全体)という意味です。

試しにfilterの中で引数をコンソールで出力してみます。

const number = ["a", "b", "b", "c", "c", "d"];

const result = number.filter((val, i, arr) => {
  console.log("val:", val);
  console.log("i:", i);
  return arr.indexOf(val) != i;
});
console.log(result); // ["b","c"]が出力される

valには要素が順番に代入されて、iには対応するインデックス番号が0〜5で代入されていますね。

続いてfilterの中でindexOfという関数がありますが、こちらは要素のインデックス番号を返す関数です。

1つ特徴としては「配列内で同じ要素が見つかった時は最初に見つけた時のインデックス番号を返す」というものです。

例えば先ほどのコードでは「”b”」「”c”」が複数ありました。

①最初に登場した”b”のインデックス番号は1になる
②次に登場した”b”のインデックス番号は2になる
③最初に登場した”c”のインデックス番号は3になる
④次に登場した”c”のインデックス番号は4になる

という具合なんですが、indexOfの裏側では、

⑤”b”は複数あるからインデックス番号は1のみを残す
⑥”c”は複数あるからインデックス番号は3のみを残す

という解釈になっています。

このindexOfの特性を上手く利用すると「インデックス番号とindexOfの結果がズレたものは重複している」と考えることができるわけです。

先ほどの解釈をもう一度見返すと、「③と⑤」「④と⑥」でインデックス番号の解釈にズレが出ているので「bとcは重複した要素である」と言えますね。

const number = ["a", "b", "b", "c", "c", "d"];

const result = number.filter((val, i, arr) => {
  // indexOfの結果とiが等しくないものは重複した要素であるはず
  return arr.indexOf(val) != i;
});
console.log(result); // ["b","c"]が出力される

パッと見ただけでは腹落ちして理解できないかもしれないので、ぜひお手元で試してみてください。

ちなみにですがfilter関数の中を「arr.indexOf(val) == i」とすると興味深いものが見れます。

const number = ["a", "b", "b", "c", "c", "d"];

const result = number.filter((val, i, arr) => {
  // ==に修正した
  return arr.indexOf(val) == i;
});
console.log(result); // ["a","b","c","d"]が出力される

こちらは重複を削除した配列が取り出せましたね。

先ほど説明した「インデックス番号とindexOfの結果がズレたものは重複している」を逆説的に考えると、「インデックス番号とindexOfの結果がズレなかったものは重複していない」という説が成り立つのです。

そのため冒頭で紹介したsetオブジェクトを使用した場合と同じく「重複削除」が実現できるわけです。

setオブジェクトが一番簡単に重複削除できる方法ですが、少し複雑なケースではfilterも試してみるようにすると良いかもしれません。

  • このエントリーをはてなブックマークに追加