【JavaScript】配列検索とは?初心者向けにわかりやすく解説

はじめに

JavaScriptで開発を進めるうえで、配列に対する処理はとてもよく使われます。 たとえばWebサイトでユーザーが入力したデータを一覧にまとめ、その中から特定のキーワードに一致する要素を見つけ出したい場面などが考えられるでしょう。

実際、配列の中身を効率的に検索することは、データの抽出や加工に欠かせません。 たとえば在庫管理システムでは商品情報を配列として保持し、その配列から特定の商品を探すことがあります。 こうした場面で素早く検索する方法を覚えておくと、開発のスピードも上がり、品質も向上しやすくなります。

本記事では、JavaScriptの配列検索に焦点を当て、初心者の皆さんでも理解しやすいようにいくつかの方法を紹介していきます。 配列検索の基礎的なメソッドから、条件に応じた検索方法まで、実務で役立つ具体的なコード例を使いながら解説していくので、ぜひ最後まで読んでみてください。

この記事を読むとわかること

  • JavaScriptの配列検索に必要な基本メソッドの使い方
  • 検索メソッドを使った実務での具体的な活用シーン
  • includesindexOf など、よく使うシンプルな検索方法
  • findfilter を用いた複数条件検索や最初のマッチだけを取り出す方法
  • 複雑な場面で役立つカスタム検索ロジックの実装例
  • 部分一致や複数要素への同時検索を行うための工夫

これらを押さえると、検索ロジックを組む際に迷いにくくなり、コードの保守もしやすくなります。 実務で活用しやすい視点も交えながら解説していきますので、初心者の皆さんでも落ち着いて学んでいきましょう。

配列検索の基本となる仕組み

JavaScriptで配列の中から特定の要素を探す方法には、いくつかの基本メソッドがあります。 代表的なものとしては indexOflastIndexOfincludes などがあります。

実際の業務シーンを考えてみましょう。 たとえばSNSアプリのコメント欄を管理する配列があり、ある特定のキーワードを含むコメントがないか調べたいとします。 こうした場面では、単純に文字列として完全一致を探すのであれば includesindexOf が活躍します。

ここでは、より基礎的なところから始めるために、まずはごくシンプルな3つのメソッドについて確認してみましょう。

indexOfメソッド

indexOf は、指定した要素が 最初に見つかったインデックス (配列の位置)を返すメソッドです。 もし要素が存在しなければ -1 を返します。

const fruits = ["apple", "banana", "orange", "banana"];
const index = fruits.indexOf("banana");
console.log(index); // 結果: 1

この例では、"banana" は 1 番目の要素として初めて登場します。 そのため fruits.indexOf("banana")1 を返します。

一方で、"grape" のように配列に存在しない要素を探す場合は -1 になるので、検索結果が見つからないときの処理を工夫する必要があります。

実務シーンでは、在庫リスト配列に商品名が含まれているかどうかを簡易的に判定したいときに便利です。 商品名が見つかったインデックスを使って、別の配列と連動して在庫数を参照するなどのロジックを組めます。

lastIndexOfメソッド

lastIndexOf は、指定した要素が最後に見つかったインデックスを返します。 indexOf の逆向き探索版と考えるとイメージしやすいかもしれません。

const fruits = ["apple", "banana", "orange", "banana"];
const lastIndex = fruits.lastIndexOf("banana");
console.log(lastIndex); // 結果: 3

同じ配列に "banana" が2つ含まれている場合、最後に見つかったのは 3 番目なので、結果は 3 となります。

実務の例としては、エラーが複数記録されているログ配列のなかで、最後に出現した特定エラーメッセージの位置を探したい場合などが考えられます。 「直近のエラーはどこで発生したのか」を特定し、その周囲のログを重点的に調べるといった作業がやりやすくなるでしょう。

includesメソッド

includes は、指定した要素が配列に含まれているかどうかを 真偽値 (true/false)で返すシンプルなメソッドです。 位置情報までは不要で、とにかく存在判定を行いたい場面で重宝します。

const fruits = ["apple", "banana", "orange"];
const isThereBanana = fruits.includes("banana");
console.log(isThereBanana); // 結果: true

たとえば入力フォームに対して禁止ワードを設定しておき、入力された文字列が禁止ワードリストに含まれているかどうかを判定したい場合などに役立ちます。 存在がわかったら後の処理でエラーメッセージを表示する、といった使い方が考えられるでしょう。

上記3つのメソッドは、いずれも文字列の完全一致を前提とした検索を行うものです。 部分一致やオブジェクトを含む配列を検索したい場合にはもう少し複雑な方法が必要になってきます。 次のセクションでは、より高度な検索が可能なメソッドを見ていきましょう。

条件に応じた検索を実現するメソッド

現実のアプリケーションでは、配列の要素が文字列だけとは限りません。 オブジェクトの配列を検索したり、特定の条件にマッチする要素だけを抜き出したりする必要が出てきます。

ここからは、複数条件検索オブジェクトの中身を調べるシーンで便利なメソッドを順に見ていきます。 オンラインショップで商品一覧から条件に合う商品を探すケースなどをイメージしながら読むと理解が進みやすいでしょう。

findメソッド

find は、コールバック関数を使って条件にマッチする最初の要素を返すメソッドです。 もし該当する要素がなければ undefined が返されます。

const products = [
  { id: 1, name: "Laptop", price: 100000 },
  { id: 2, name: "Mouse", price: 2000 },
  { id: 3, name: "Keyboard", price: 5000 },
  { id: 4, name: "Laptop", price: 120000 }
];

// 価格が3千円以上かつ、商品名が "Laptop" である最初の要素
const targetItem = products.find((item) => {
  return item.price >= 3000 && item.name === "Laptop";
});

console.log(targetItem);
// 結果: { id: 1, name: "Laptop", price: 100000 }

コールバック関数は、配列の各要素に対して真偽値を返す処理を行います。 find はこれを順番に実行して、最初に true となった要素を返して終了します。

実務シーンの一例としては、ユーザー登録情報を配列で管理し、特定のメールアドレスで登録されたユーザー情報を最初に1件だけ取り出したいときに便利です。 あらゆる登録情報を全部取り出す必要はなく、あくまで「最初にヒットした人」だけ確認したい場合などに効率的です。

filterメソッド

filter は、コールバック関数の条件に合致したすべての要素を新しい配列として返します。 名前のとおり「フィルタをかける」イメージで、条件に合わないものは排除し、合うものだけを集めるのに適しています。

const products = [
  { id: 1, name: "Laptop", price: 100000 },
  { id: 2, name: "Mouse", price: 2000 },
  { id: 3, name: "Keyboard", price: 5000 },
  { id: 4, name: "Laptop", price: 120000 }
];

// 価格が1万円以上のすべての商品を抽出
const expensiveItems = products.filter((item) => item.price >= 10000);

console.log(expensiveItems);
// 結果:
// [
//   { id: 1, name: "Laptop", price: 100000 },
//   { id: 4, name: "Laptop", price: 120000 }
// ]

ここでは price >= 10000 という条件に合った商品だけが抽出され、新しい配列が返されます。 オンラインストアで検索条件を指定し、該当する商品一覧だけを表示したいときなどにまさにぴったりです。

さらに複数条件を組み合わせたい場合も、コールバック関数の中で &&(AND条件)や ||(OR条件)を使えば簡単に実現できます。 たとえば「価格が5000円以上、かつ商品名に"Laptop"が含まれるもの」を探したいといったケースがスムーズに書けるでしょう。

findIndexメソッド

findIndex は、コールバック関数の条件に合致した要素のインデックスを返すメソッドです。 該当する要素が見つからなかった場合は -1 が返されます。

const products = [
  { id: 1, name: "Laptop", price: 100000 },
  { id: 2, name: "Mouse", price: 2000 },
  { id: 3, name: "Keyboard", price: 5000 }
];

const indexLaptop = products.findIndex((item) => item.name === "Laptop");
console.log(indexLaptop); // 結果: 0

要素そのものではなく、あえてインデックスを取得する理由としては、該当要素の直前・直後のデータもあわせて処理したい場面が考えられます。 たとえば購入履歴の配列からユーザーが購入した順番を参照し、その1つ前のアイテムをチェックして何かしらの提案を表示する、といった具合です。

これらのメソッドを使うと、オブジェクト配列から特定の属性にマッチする要素を手軽に検索できます。 実務のアプリケーションでは、検索だけでなくその結果をもとに画面表示を切り替えたり、在庫数やユーザー権限を更新したりといった流れが自然に組めます。

部分一致検索の考え方

ここまでは、基本的に「完全一致」を前提とした検索方法を紹介してきました。 しかし実務では「名前に 'Laptop' が含まれている商品を探したい」など、部分一致による検索が求められることも少なくありません。

たとえばECサイトの検索窓に「lap」と入力したら「Laptop」がヒットしてほしいケースです。 こういった部分一致を実現するには、文字列メソッドを組み合わせて検索を行うアプローチがよく使われます。

const products = [
  { id: 1, name: "Laptop stand", price: 3000 },
  { id: 2, name: "Desk", price: 10000 },
  { id: 3, name: "Laptop Case", price: 2000 }
];

const keyword = "lap"; // ユーザーが入力した検索キーワード

// 文字列を小文字に変換して部分一致を判定
const filteredItems = products.filter((item) => {
  return item.name.toLowerCase().includes(keyword.toLowerCase());
});

console.log(filteredItems);
// 結果:
// [
//   { id: 1, name: "Laptop stand", price: 3000 },
//   { id: 3, name: "Laptop Case", price: 2000 }
// ]

ここでは以下の手順で部分一致検索を実現しています。

  1. 配列要素の nametoLowerCase() で小文字に変換
  2. ユーザーが入力したキーワードも小文字化
  3. includes で部分一致判定

こうすることで、大小文字が混在しているデータに対しても確実に部分一致検索を実装できます。 もし前方一致や後方一致のように、より特化した判定をしたい場合は文字列メソッドの startsWithendsWith を利用すると便利でしょう。

正規表現を用いた高度な検索

部分一致よりも複雑なパターン(数字が何桁続いているか、特定の文字の組み合わせかどうかなど)を判定したいときは正規表現が有効です。 たとえば製品コードに特定のルールがある場合や、メールアドレスの形式をざっくりチェックしたいケースなどが挙げられます。

const users = [
  { name: "Alice", email: "alice@example.com" },
  { name: "Bob", email: "bob#example.com" },
  { name: "Charlie", email: "charlie@example.com" }
];

// 簡易的に "@" と "." を含む文字列をメールとして判定する正規表現
const emailPattern = /.+@.+\..+/;

const validEmails = users.filter((user) => {
  return emailPattern.test(user.email);
});

console.log(validEmails);
// 結果:
// [
//   { name: "Alice", email: "alice@example.com" },
//   { name: "Charlie", email: "charlie@example.com" }
// ]

この例では、単純に @. が含まれているかだけを正規表現でチェックし、その条件を満たすユーザーだけを抽出しています。 実際の業務ではより精緻な正規表現を用いることが多いです。

正規表現を使えば、特定の文字数や文字種、パターンを厳密にチェックできるので、入力データが一定のルールを満たしているかどうかを検索して絞り込む際に非常に便利です。 ただし、正規表現は表記ルールがやや複雑なので、読む人が理解できるようにコメントや分割表記など工夫することが大切になります。

配列検索を活用する実務シーンの具体例

ここで少し視点を変えて、どのように配列検索を実務へ落とし込むかをもう少し詳しく考えてみましょう。 検索自体はコードで実装できても、その後の処理がどう繋がっていくかイメージできるようになると、より応用が効くようになります。

シーン1: ECサイトの商品検索

多くのECサイトでは、商品情報をオブジェクト配列として保持し、ユーザーが検索バーで入力したキーワードをもとに filter などを使って絞り込みを行います。 複数のキーワードに対応するために、スペース区切りされた文字列を分割して、すべてのキーワードを含むものだけ表示するといった実装も可能です。

ユーザーが「laptop stand」というふうにスペースで2つの単語を入力した場合、どちらも部分一致する商品だけを一覧表示するイメージです。 さらに価格帯なども同時に指定できるようにするときは、フィルタ条件にprice >= 最低価格 && price <= 最高価格といった追加条件を組み込むことになります。

このように、単なる配列検索でも工夫次第で多彩な検索体験を提供できます。 ユーザーがどんな条件で検索したいのかを明確にして、それをコードとしてシンプルに反映することが大切です。

シーン2: 管理システムでのデータ抽出

企業内部の管理システムや在庫管理などでは、複数の条件に該当するデータだけを素早く抜き出したい場面が頻繁にあります。 たとえば「在庫数が0以上かつステータスが 'active' の商品をすべて取得して、入荷リマインドをセットする」などの要件が出てくるでしょう。

const items = [
  { id: 1, name: "Laptop", stock: 10, status: "active" },
  { id: 2, name: "Mouse", stock: 0, status: "inactive" },
  { id: 3, name: "Monitor", stock: 2, status: "active" },
  { id: 4, name: "Cable", stock: 0, status: "active" }
];

const activeInStock = items.filter((item) => {
  return item.stock > 0 && item.status === "active";
});

console.log(activeInStock);
// 結果: [{ id: 1, name: "Laptop", stock: 10, status: "active" },
//       { id: 3, name: "Monitor", stock: 2, status: "active" }]

こうした抽出結果をもとに、自動的に発注メールを送る、あるいは在庫を表示する画面に反映するなどの処理を追加できます。 プログラムの規模が大きくなると、サーバーサイドでデータベースに対するクエリ検索を行うケースも多いですが、フロントエンド側のJavaScriptで一時的に配列検索を行う場面は依然として珍しくありません。

このような場面でも、どの条件を検索に使うかを明確にし、複数の条件をわかりやすい形でコードに落とし込むことがポイントになってきます。

シーン3: ユーザー情報の参照・権限チェック

Webアプリケーションによっては、ログインユーザーの権限レベルを配列で管理している場合があります。 「特定の権限IDを持つユーザーを一覧表示する」「ログインIDがすでに登録済みかどうかをチェックする」といった処理は、配列検索があるとスムーズに書けます。

const users = [
  { id: 1, username: "alice", roles: ["admin", "editor"] },
  { id: 2, username: "bob", roles: ["viewer"] },
  { id: 3, username: "charlie", roles: ["editor"] }
];

// "editor" 権限を持つユーザーを全員抽出
const editors = users.filter((user) => user.roles.includes("editor"));

console.log(editors);
// 結果:
// [
//   { id: 1, username: "alice", roles: ["admin", "editor"] },
//   { id: 3, username: "charlie", roles: ["editor"] }
// ]

こういった権限管理を実装すると、特定の権限を持つユーザーだけに特定の画面を見せたり、操作を許可したりといった制御が可能になります。 配列検索の知識が身につくと、シンプルなロジックで制御が組めるため、権限管理のコードも読みやすくなりやすいでしょう。

複数の権限を持つユーザーへの対応など、状況が複雑になるほど検索条件をわかりやすい関数にまとめると保守しやすくなります。

カスタム関数で検索ロジックを再利用する

配列検索の処理は、短いコードで書ける場合でも、専用のカスタム関数として分けておくと後々のメンテナンスがしやすくなります。 特に同じ検索処理をプロジェクト内の複数箇所で使い回す場合、コールバックを毎回書くよりも関数として切り出すほうが読みやすい場面が出てくるでしょう。

// カスタム検索関数の例
function filterByNameIncludes(items, keyword) {
  return items.filter((item) => {
    return item.name.toLowerCase().includes(keyword.toLowerCase());
  });
}

// 実務で商品一覧をフィルタリングする
const products = [
  { id: 1, name: "Laptop stand", price: 3000 },
  { id: 2, name: "Desk", price: 10000 },
  { id: 3, name: "Laptop Case", price: 2000 }
];

const result = filterByNameIncludes(products, "lap");
console.log(result);

例えばこの filterByNameIncludes 関数を作っておくと、あちこちの画面で同様のフィルタ機能が必要になったとき、関数呼び出しだけで再利用できます。 また、後から検索条件を変更したい場合も、この関数内部を修正するだけで全画面に適用されるので、保守性の面でもメリットが大きいです。

パフォーマンスを意識した検索

配列検索は便利ですが、配列の要素数が極端に多い場合にはパフォーマンスを気にする必要が出てきます。 たとえば数万件〜数十万件ものデータをフロントエンド側で保持し、複雑な検索処理を走らせると、表示が遅くなったりブラウザが固まったりする可能性もあります。

パフォーマンス対策としては以下のようなアプローチが考えられます。

  • 配列サイズが大きすぎる場合は、サーバーサイドで検索結果を絞り込んでからクライアントに送る
  • キャッシュを使って、以前検索した結果と同じ条件なら再利用する
  • 一度にすべての検索結果を表示せず、ページングや無限スクロールで段階的に取得する
  • よく検索する項目に対しては、あらかじめマップやセット(MapSet)構造を使う

JavaScriptの配列検索メソッド自体は、たとえ数万件のデータでも、環境によっては十分に高速です。 ただし、複雑な条件を何度も繰り返し実行するような場面では、「検索条件を絞りやすい形でデータを保持する」「サーバーと分業する」など、実装レベルを超えた設計面の工夫が求められます。

多次元配列やネストされたオブジェクトの検索

実際の業務データはもっと複雑な構造をしている場合があります。 配列の中にオブジェクトがあり、そのオブジェクトの中にも配列があるといった「多次元配列」や「深いネスト構造」です。

例えば、社員情報を部署ごとにまとめ、部署ごとに配列を持つオブジェクトを作っている場合などが挙げられます。 こういった場合は単純な filterfind だけでは完結せず、再帰処理ループを使って深い階層までたどりながら検索を行う必要があります。

const company = {
  departments: [
    {
      name: "Sales",
      employees: [
        { id: 1, name: "Alice", role: "manager" },
        { id: 2, name: "Bob", role: "sales" }
      ]
    },
    {
      name: "Development",
      employees: [
        { id: 3, name: "Charlie", role: "engineer" },
        { id: 4, name: "Dave", role: "engineer" }
      ]
    }
  ]
};

function findEmployeeByName(data, searchName) {
  for (const dept of data.departments) {
    for (const emp of dept.employees) {
      if (emp.name === searchName) {
        return emp;
      }
    }
  }
  return null;
}

console.log(findEmployeeByName(company, "Charlie"));
// 結果: { id: 3, name: "Charlie", role: "engineer" }

上記の例はネストされたいくつもの配列を入れ子にしていて、結果を見つけたら即座に返す形になっています。 もしすべての該当ユーザーを集めたいのであれば、find ではなく filter をイメージした実装に変えて、結果を配列に追加していくように書くことも可能です。

実務では、このようにデータ構造自体が複雑になるほど、検索のアルゴリズムや実装パターンの工夫が重要になります。 コードが長くなりがちなので、しっかりテストしながら段階的に実装し、意図通りに動作することを確認していきましょう。

カスタムソートとの組み合わせ

配列検索で候補となる要素を抽出したあと、それらの要素をユーザーにとって見やすい形に並べ替える場合があります。 このようなシーンでは、カスタムソートと組み合わせることで、よりユーザーフレンドリーな表示が可能です。

// 価格が1万円以上のアイテムを検索して価格が安い順に並べ替える例
const filteredAndSortedItems = products
  .filter((item) => item.price >= 10000)
  .sort((a, b) => a.price - b.price);

ここでは、まず filter で抽出した配列に対して、そのまま sort をチェーンしています。 ソート用のコールバック関数 a.price - b.price は、小さい価格が前に来るように並べ替えるロジックです。

ユーザーが検索条件を入力したあと、「安い順」「高い順」「名前順」のように並べ替えを選択することはよくあるので、あらかじめ sort 処理を用意しておくと後から拡張しやすいでしょう。

大量データをソートし続けると処理負荷が高くなる場合があります。サーバーでのソートやページネーションの検討も重要です。

テストやデバッグのポイント

配列検索のロジックは、条件が複数になると簡単にバグが紛れ込みやすくなります。 以下のような点に気をつけながらテストケースを用意してみるといいでしょう。

  • 検索結果が「0件」になるケース
  • 大文字小文字が混在しているケース
  • 部分一致でヒットするはずがヒットしない、あるいは逆に余分な要素がヒットするケース
  • オブジェクトのキー名が間違っているケース
  • ユーザーが空文字や特殊文字を入力した場合

また、引数として渡すデータの型やフォーマットが想定と異なる場合、思わぬエラーや結果不一致につながることがあります。 テスト時点でこういったパターンを洗い出し、しっかり確認しておくことが重要です。 特にチーム開発では単体テストを行い、あらゆるケースに対応できることを保証しておくと安心できます。

まとめ

ここまで、JavaScript 配列検索の多彩な方法や実務における活用シーンを紹介してきました。 indexOfincludes のようにシンプルなメソッドから始まり、findfilter、あるいは正規表現を組み合わせた部分一致検索、ネスト構造への対応、パフォーマンスの考慮など、実際の開発で遭遇する多くのシーンに触れています。

初心者の皆さんにとって、配列検索はコードを書くうえで必要不可欠のスキルと言えるでしょう。 ここで紹介したさまざまなメソッドやテクニックを、ぜひ実際の開発場面で試してみてください。 たとえば小さなサンプルプロジェクトを作成し、ユーザーが入力したキーワードでデータを絞り込んで画面に表示させるところから始めると理解が深まります。

いろいろなケースを実装していくうちに、「配列検索の結果をどのタイミングで、どうやって利用するのか」という流れが自然と頭に入ってくるでしょう。 最終的には、検索結果に対して更新処理や通知処理などを組み合わせ、アプリケーション全体の機能を豊かにしていくことができます。

皆さんが配列検索の知識を活かして、よりわかりやすく柔軟なコードを書けるようになることを願っています。 以上で本記事の解説は終了です。 最後まで読んでいただきありがとうございました。

JavaScriptをマスターしよう

この記事で学んだJavaScriptの知識をさらに伸ばしませんか?
Udemyには、現場ですぐ使えるスキルを身につけられる実践的な講座が揃っています。