JavaScript Tips | 配列ユーティリティ:OR 条件検索

JavaScript JavaScript
スポンサーリンク

何をしたいユーティリティか:「OR 条件検索」

「OR 条件検索」は、配列の中から「いくつかの条件のうち、どれか1つでも満たしていればOK」という要素を探す処理です。
論理式でいう「A または B または C」の“OR(または)”です。

業務だと、例えばこういう場面で使います。

エラーログか警告ログのどちらかを全部取りたい。
「admin か editor」のユーザーを抽出したい。
「在庫ゼロか、価格が高すぎる」商品を見つけたい。

ポイントは、「全部満たす必要がある AND 条件」とは違い、どれか1つでも条件を満たせばヒットするということです。


基本形:OR 条件で1件だけ見つける findByAny

「どれか1つでも条件を満たす最初の1件」を返す

まずは、「複数条件のうち、どれか1つでも満たす最初の1件」を探すユーティリティです。

function findByAny(array, predicates) {
  if (!Array.isArray(array)) {
    return undefined;
  }
  if (!Array.isArray(predicates) || predicates.length === 0) {
    return undefined;
  }

  return array.find((item, index) =>
    predicates.some((p) => typeof p === "function" && p(item, index))
  );
}
JavaScript

ここでの重要ポイントをかみ砕きます。

predicates は「条件関数の配列」です(OR でつなぎたい条件をここに詰める)。
some は「1つでも true があれば true」を返す関数です。
つまり、「複数条件のうち、どれか1つでも true なら、その要素はヒット」とみなします。
array.find(...) なので、「最初にヒットした1件」だけ返し、なければ undefined を返します。

これが、OR 条件検索の基本形です。

例題:エラーか警告のログを1件だけ探す

const logs = [
  { level: "info",    message: "OK" },
  { level: "warning", message: "Slow" },
  { level: "error",   message: "Failed" },
];

const isError   = (log) => log.level === "error";
const isWarning = (log) => log.level === "warning";

const firstImportant = findByAny(logs, [isError, isWarning]);

console.log(firstImportant);
// { level: "warning", message: "Slow" }
JavaScript

「error または warning」のうち、最初に出てきたログ(warning)が返ってきます。


OR 条件で「全部ほしい」パターン findAllByAny

「どれか1つでも条件を満たす要素を全部」取りたい

次は、「最初の1件」ではなく、「OR 条件を満たすものを全部ほしい」パターンです。

function findAllByAny(array, predicates) {
  if (!Array.isArray(array)) {
    return [];
  }
  if (!Array.isArray(predicates) || predicates.length === 0) {
    return [];
  }

  return array.filter((item, index) =>
    predicates.some((p) => typeof p === "function" && p(item, index))
  );
}
JavaScript

find が「最初の1件」なのに対して、filter は「条件を満たすもの全部」です。
中身のロジックは findByAny と同じで、「some で OR 条件をまとめている」のがポイントです。

例題:エラーか警告のログを全部取得

const logs = [
  { level: "info",    message: "OK" },
  { level: "warning", message: "Slow" },
  { level: "error",   message: "Failed" },
  { level: "debug",   message: "Detail" },
];

const isError   = (log) => log.level === "error";
const isWarning = (log) => log.level === "warning";

const importantLogs = findAllByAny(logs, [isError, isWarning]);

console.log(importantLogs);
/*
[
  { level: "warning", message: "Slow" },
  { level: "error",   message: "Failed" },
]
*/
JavaScript

「error または warning」のログだけが抽出されています。


AND 条件との違いをはっきり意識する

every(AND)と some(OR)の違い

複数条件検索には、AND と OR の2種類があります。

AND 条件(かつ)
すべての条件を満たす必要がある。
predicates.every(...) を使う。

OR 条件(または)
どれか1つでも条件を満たせばよい。
predicates.some(...) を使う。

例えばユーザー検索で、

const isActive = (u) => u.active;
const isAdmin  = (u) => u.role === "admin";
JavaScript

としたとき、

「active かつ admin」 → AND 条件 → every([isActive, isAdmin])
「active または admin」 → OR 条件 → some([isActive, isAdmin])

となります。

ここを取り違えると、「本当はどれか1つでよかったのに、全部満たさないとヒットしない」など、業務上のバグにつながります。
ユーティリティ名で findByAll(AND)と findByAny(OR)を分けておくと、意図が読みやすくなります。


OR 条件検索を業務ロジックに組み込む例

「admin か editor のユーザーを全部取得」

const users = [
  { id: 1, role: "user" },
  { id: 2, role: "admin" },
  { id: 3, role: "editor" },
  { id: 4, role: "guest" },
];

const isAdmin  = (u) => u.role === "admin";
const isEditor = (u) => u.role === "editor";

const privileged = findAllByAny(users, [isAdmin, isEditor]);

console.log(privileged);
/*
[
  { id: 2, role: "admin" },
  { id: 3, role: "editor" },
]
*/
JavaScript

「admin または editor」という OR 条件を、関数の組み合わせで表現できています。

「在庫ゼロか価格が高すぎる商品をチェック」

const items = [
  { id: 1, stock: 0,  price: 500 },
  { id: 2, stock: 10, price: 1500 },
  { id: 3, stock: 5,  price: 4000 },
];

const isOutOfStock = (item) => item.stock === 0;
const isTooExpensive = (item) => item.price > 3000;

const problematic = findAllByAny(items, [isOutOfStock, isTooExpensive]);

console.log(problematic);
/*
[
  { id: 1, stock: 0,  price: 500 },
  { id: 3, stock: 5,  price: 4000 },
]
*/
JavaScript

「在庫ゼロまたは高すぎる」という OR 条件で、問題のある商品だけを抽出できます。


手を動かして OR 条件検索の感覚をつかむ

コンソールで、次のコードを実際に打ってみてください。

function findByAny(array, predicates) {
  if (!Array.isArray(array)) return undefined;
  if (!Array.isArray(predicates) || predicates.length === 0) return undefined;
  return array.find((item, index) =>
    predicates.some((p) => typeof p === "function" && p(item, index))
  );
}

function findAllByAny(array, predicates) {
  if (!Array.isArray(array)) return [];
  if (!Array.isArray(predicates) || predicates.length === 0) return [];
  return array.filter((item, index) =>
    predicates.some((p) => typeof p === "function" && p(item, index))
  );
}

const logs = [
  { level: "info",    message: "OK" },
  { level: "warning", message: "Slow" },
  { level: "error",   message: "Failed" },
];

const isError   = (log) => log.level === "error";
const isWarning = (log) => log.level === "warning";

console.log(findByAny(logs, [isError, isWarning]));
console.log(findAllByAny(logs, [isError, isWarning]));
JavaScript

「どのログがヒットするか」「条件を1つ増やしたらどう変わるか」を、自分の手で試してみてください。


まとめ:OR 条件検索ユーティリティで“複雑な検索条件”を整理する

OR 条件検索は、「どれか1つでも条件を満たせばOK」という柔軟な絞り込みを実現するための道具です。
業務コードでは、AND と OR が混ざった複雑な条件がよく出てきますが、

条件を小さな関数として分解する。
AND は findByAll / OR は findByAny に任せる。
検索ロジックを「配列ユーティリティ」として外出しする。

こうしておくと、検索条件の変更・追加・テストがとても楽になります。

プロジェクトに

export function findByAny(...) { ... }
export function findAllByAny(...) { ... }
JavaScript

のような関数を置き、「“A または B”で探したくなったら必ずこれを通す」と決めておくと、
検索ロジックが整理されて、コードの“業務レベル感”が一段上がります。

タイトルとURLをコピーしました