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

JavaScript JavaScript
スポンサーリンク

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

「AND 条件検索」は、配列の中から「複数の条件をすべて満たす要素」だけを探す処理です。
論理式でいう「A かつ B かつ C」の“AND(かつ)”です。

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

  • 「active かつ role=admin のユーザーだけ欲しい」
  • 「在庫あり かつ 価格が 1000〜3000 円の商品だけ欲しい」
  • 「エラーではなく かつ 警告フラグが立っているログだけ欲しい」

ポイントは、1つでも条件を満たさなければ“対象外”になることです。
OR 条件(どれか1つでOK)とは真逆の性質を持っています。


基本形:AND 条件で1件だけ見つける findByAll

「すべての条件を満たす最初の1件」を返す

まずは、「複数条件をすべて満たす最初の1件」を探すユーティリティからいきます。

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

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

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

  • predicates は「条件関数の配列」です(AND でつなぎたい条件をここに詰める)
  • every は「全部 true なら true、1つでも false があれば false」を返す関数です
  • つまり、「複数条件のすべてを満たした要素だけがヒット」します
  • array.find(...) なので、「最初にヒットした1件」だけ返し、なければ undefined を返します

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

例題:active かつ role=admin のユーザーを1件探す

const users = [
  { id: 1, name: "A", active: true,  role: "user" },
  { id: 2, name: "B", active: false, role: "admin" },
  { id: 3, name: "C", active: true,  role: "admin" },
];

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

const user = findByAll(users, [isActive, isAdmin]);

console.log(user);
// { id: 3, name: "C", active: true, role: "admin" }
JavaScript

条件はこうです。

  • 条件1:active === true
  • 条件2:role === "admin"

この両方を満たす最初のユーザー(id=3)が返ってきます。
どちらか片方だけ満たしていても、AND 条件なのでヒットしません。


AND 条件で「全部ほしい」パターン findAllByAll

「条件をすべて満たす要素を全部」取りたい

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

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

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

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

例題:在庫あり&価格 1000〜3000 円の商品を全部取得

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

const hasStock      = (item) => item.stock > 0;
const priceInRange  = (item) => item.price >= 1000 && item.price <= 3000;

const result = findAllByAll(items, [hasStock, priceInRange]);

console.log(result);
/*
[
  { id: 2, stock: 10, price: 1500 },
  { id: 4, stock: 3,  price: 2500 },
]
*/
JavaScript

「在庫あり」かつ「価格が範囲内」の商品だけが抽出されています。
どちらか片方を満たさない商品(id=1,3)は除外されています。


AND 条件と OR 条件の違いを体で覚える

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])

となります。

ここを取り違えると、「本当は両方満たしてほしかったのに、片方だけで通ってしまう」など、
業務上のバグに直結します。
ユーティリティ名で findByAll(AND)と findByAny(OR)を分けておくと、意図が読みやすくなります。


条件を「関数の配列」にするメリット

条件を分解して再利用できる

isActiveisAdminhasStockpriceInRange のように、
条件を小さな関数として分けておくと、次のような良いことがあります。

  • 条件ごとに単体テストしやすい
  • 組み合わせを変えるだけで別の検索が書ける
  • 「この検索はどんな条件で絞っているか」が読みやすい

例えばユーザー検索で、

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

と分けておけば、

  • 「active かつ admin」 → [isActive, isAdmin]
  • 「active かつ editor」 → [isActive, isEditor]

のように、条件の組み合わせだけで検索のバリエーションを増やせます。

ユーティリティ名で意図を表現する

findByAll(AND)と findAllByAll を用意しておくと、
「この検索は“全部満たす必要がある”」ことが関数名だけで伝わります。

業務コードでは、「条件の意味が一目で分かる」ことがとても大事です。
every をそのまま書くより、ユーティリティ名で意図を表現するほうが読みやすくなります。


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

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

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

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

const users = [
  { id: 1, active: true,  role: "user" },
  { id: 2, active: false, role: "admin" },
  { id: 3, active: true,  role: "admin" },
];

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

console.log(findByAll(users, [isActive, isAdmin]));
console.log(findAllByAll(users, [isActive, isAdmin]));
JavaScript

「どのユーザーがヒットするか」「条件を1つ増やしたらどう変わるか」を、自分の手で試してみてください。
everysome に変えてみて、「AND と OR の違い」を体感するのもおすすめです。


まとめ:AND 条件検索ユーティリティで“厳密な絞り込み”を標準化する

AND 条件検索は、「複数の条件をすべて満たす要素だけを厳密に絞り込みたい」ときの基本ツールです。

プロジェクトに次のような関数を置いておくイメージです。

export function findByAll(...) { ... }
export function findAllByAll(...) { ... }
JavaScript

そして、「複数条件を“かつ”で絞りたくなったら、必ずこれを通す」と決めておく。
そうすると、検索ロジックが整理されて、条件変更やテストがとてもやりやすくなります。

AND と OR を意識して、「これは全部満たしてほしい条件なのか? それともどれか1つでいいのか?」と自分に問いながら書けるようになると、
配列検索のコードが一気に“業務レベル”に近づきます。

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