【JavaScript】配列から条件に合う要素を取り出す方法|filter・find・findIndex・someの使い分け

配列から「条件に合う要素を取り出す」と一口に言っても、全部欲しいのか/最初の1件でいいのか/あるかどうか知りたいだけなのかで使うメソッドが変わります。ここを押さえると、コードが短く・読みやすく・速くなります。

この記事の結論(目的別の使い分け):条件に合うすべてfilter()最初の1件find()位置(添字)findIndex()存在するかsome()全部が条件を満たすかevery()
スポンサーリンク

条件に合うものを全部取り出す:filter()

filter() はコールバックが true を返した要素だけを集めた新しい配列を返します。元の配列は変更しません。

filter() で偶数だけ取り出す
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

const even = numbers.filter((n) => n % 2 === 0);
console.log(even); // [2, 4, 6, 8, 10]

// 条件を関数に切り出してもよい
const isBig = (n) => n > 7;
console.log(numbers.filter(isBig)); // [8, 9, 10]
filter()条件に合う要素が無くてもエラーにならず、空配列 [] を返します。「0件かどうか」は result.length === 0 で判定できます。

最初に条件に合う1件を取り出す:find()

1件だけ欲しいときに filter()[0] とするのは無駄です。find() なら最初に条件を満たした要素を返し、見つかった時点で探索を止めるので効率的です。

find() で最初の偶数
const numbers = [1, 2, 3, 4, 5];

const firstEven = numbers.find((n) => n % 2 === 0);
console.log(firstEven); // 2

// 見つからないときは undefined
console.log(numbers.find((n) => n > 100)); // undefined
filter と find の戻り値の違いに注意:filter()配列(見つからなければ [])、find()要素そのもの(見つからなければ undefined)を返します。find() の結果はそのまま使う前に if (found) { ... } で存在チェックすると安全です。

位置や「最後の1件」を取り出す:findIndex() / findLast()

要素そのものではなく何番目か(添字)が欲しいときは findIndex()末尾側から最初に条件に合う1件が欲しいときは findLast() を使います。

findIndex / findLast / findLastIndex
const numbers = [1, 2, 3, 4, 5, 6];

console.log(numbers.findIndex((n) => n > 3));     // 3(最初に3を超えるのは添字3の「4」)
console.log(numbers.findLast((n) => n % 2 === 0)); // 6(末尾側から最初の偶数)
console.log(numbers.findLastIndex((n) => n % 2 === 0)); // 5
findLast()findLastIndex()ES2023 で追加された比較的新しいメソッドです。モダンブラウザと新しめのNode.jsで使えます。見つからない場合、findIndex()findLastIndex()-1 を返します。

取り出さずに「あるか/全部か」を判定する:some() / every()

要素そのものは要らず、条件を満たすものが存在するかだけ知りたいなら some()全部が条件を満たすかなら every() を使います。どちらも真偽値を返します。

some() / every()
const numbers = [1, 2, 3, 4, 5];

console.log(numbers.some((n) => n > 4));   // true(4より大きいものがある)
console.log(numbers.every((n) => n > 0));  // true(全部0より大きい)
console.log(numbers.every((n) => n % 2 === 0)); // false(奇数がある)

オブジェクトの配列を条件で取り出す

実務でよくあるのがオブジェクトの配列から探すケースです。コールバックでプロパティを参照し、&& で複合条件も書けます。

id検索・複合条件
const users = [
  { id: 1, name: "John", age: 30 },
  { id: 2, name: "Jane", age: 25 },
  { id: 3, name: "Bob", age: 40 },
];

// idで1件だけ取り出す
console.log(users.find((u) => u.id === 2)); // { id: 2, name: "Jane", age: 25 }

// 30歳以上を全部
console.log(users.filter((u) => u.age >= 30).map((u) => u.name)); // ["John", "Bob"]

// 複合条件(25歳以上 かつ J で始まる名前)
console.log(
  users.filter((u) => u.age >= 25 && u.name.startsWith("J")).map((u) => u.name)
); // ["John", "Jane"]

使い分け早見表

やりたいこと メソッド 見つからない時
条件に合うすべて filter() [](空配列)
最初の1件 find() undefined
最後の1件 findLast() undefined
位置(添字) findIndex() -1
存在するか some() false
全部が満たすか every() true(空配列時)

よくある質問(FAQ)

Q条件に合う要素を1件だけ取り出すには?
Afind() を使います。最初に条件を満たした要素を返し、見つからなければ undefined を返します。全件が必要なときは filter()、位置(添字)が必要なら findIndex() を使います。
Qfind と filter はどう使い分けますか?
A1件だけなら find()、すべてなら filter() です。戻り値も違い、find() は要素そのもの(無ければ undefined)、filter() は配列(無ければ [])を返します。1件で済むのに filter()[0] とすると無駄な探索が発生します。
Qオブジェクトの配列を特定のプロパティで探すには?
Aarray.find((item) => item.id === targetId) のように、コールバックでプロパティを参照します。複数条件は &&|| で組み合わせられます。
Q条件に合うものが「あるか」だけ知りたい場合は?
Asome() を使います。1つでも条件を満たせば true を返します。逆に「全部が条件を満たすか」は every() です。要素を取り出す必要がない判定では、これらが最も簡潔です。

まとめ

配列から条件に合う要素を取り出すメソッドの使い分けを整理します。

  • 条件に合うすべてfilter()(無ければ []
  • 最初の1件find()(無ければ undefined
  • 位置findIndex()最後の1件findLast()
  • 存在チェックsome()全件チェックevery()
  • オブジェクト配列はコールバックでプロパティ参照+&& で複合条件

関連として、配列の map・filter・reduce の使い方(実践パターン集)indexOf メソッドの使い方(検索と find との違い)some() で条件に一致するか判定する方法もあわせて読むと、配列操作の引き出しが増えます。