Tips

JavaScriptで重複チェック、重複削除など検索(絞り込み)をする方法【filter, indexOf, set, startsWith, endsWith, test】

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

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も試してみるようにすると良いかもしれません。

JavaScriptでよく使う検索メソッド

先ほどの例のような「〇〇があるか?」という検索系の機能はたびたび登場します。

また検索の種類も完全一致か部分一致かなど微妙に違うことがあります。

初学者の方が覚えておきべきJavaScriptの検索メソッドを簡単に紹介しておきます。

JavaScriptのindexOfの使い方

まずは先ほども紹介したindexOfです。

indexOfは引数に指定したものがある場合、インデックス番号を返します。

インデックス番号なので0から数えるのを注意してください。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <link rel="stylesheet" href="./style.css" />
    <script src="./script.js" defer></script>
  </head>
  <body>
    <div class="container"></div>
    <div class="wrapper"></div>
  </body>
</html>
const text1 = "私の学籍番号は10番です。";
const result1 = text1.indexOf("1");

const container = document.querySelector(".container");
container.innerHTML = text1;
const wrapper = document.querySelector(".wrapper");
wrapper.innerHTML = result1;

「私の学籍番号は10番です。」という文章のなかで「1」はインデックス番号の7番目にあるので7を返しました。

逆に無い場合は-1を返すようになっていますので、「indexOfが-1でなければ〇〇が含まれている」という条件分岐も作れますね。

JavaScriptのstartsWithとendsWithの使い方

続いてstartsWithを使うことで、「〇〇で始まるか?」という検索ができることができます。

先ほどのコードでscript.jsについて以下のように変更します。

const text1 = "私の学籍番号は10番です。";
// ここを変更
const result2 = text1.startsWith("私");

const container = document.querySelector(".container");
container.innerHTML = text1;
const wrapper = document.querySelector(".wrapper");
// ここを変更
wrapper.innerHTML = result2;

同じような用途でendsWithを使うと「〇〇で終わるか?」という検索ができます。

const text1 = "私の学籍番号は10番です。";
// ここを変更
const result3 = text1.endsWith("。");

const container = document.querySelector(".container");
container.innerHTML = text1;
const wrapper = document.querySelector(".wrapper");
// ここを変更
wrapper.innerHTML = result3;

例では日本語の文章のなかで使ってますが、数字や英語でも対応することができます。

商品IDが規則性のある数字の組み合わせになっていれば特定の商品だけで絞り込むなどの使い方ができますね。

JavaScriptのtestの使い方

検索系をするときに正規表現を使うこともできてJavaScriptの場合はtestというメソッドがあります。

初学者の方からすると正規表現は難しく感じるかもしれませんが、自分で作ることはなくて調べることでほとんど対応できます。

const text1 = "私の学籍番号は10番です。";
// ここを変更
const re = /[0-9]/;
const result4 = re.test(text1);

const container = document.querySelector(".container");
container.innerHTML = text1;
const wrapper = document.querySelector(".wrapper");
// ここを変更
wrapper.innerHTML = result4;

上記のre=/[0-9]/という正規表現で「数字が含まれるか?」という条件にしました。

testメソッドを使うことで自分で設定した正規表現の条件に合うかtrue/falseで確認することができます。

今回の記事の作成にあたり以下の本を参考にしましたので良ければどうぞ。

今回の記事を作成するのに参考にした本はこちらから

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