配列を条件で2つに分ける

条件に合うものと合わないものを、1回のループで2つの配列に分けます。 filter() を2回書く方法との違い、条件の否定を書き間違えて件数が合わなくなる罠まで確かめます。

実行して検証済み処理系Node 22.22.3対応ES2015難易度●●○○○目安7更新

答え

条件は1か所だけ書きます。

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
[ [ 2, 4 ], [ 1, 3, 5 ] ]
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
[ { id: 1, ok: true } ] [ { id: 2, ok: false } ]

標準のメソッドはありません。これだけで足ります。

受け取る側は分割代入で書きます。

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
[ 2, 4 ] [ 1, 3, 5 ]
javascript
const users = [
{ name: 'a', age: 20 },
{ name: 'b', age: null },
{ name: 'c', age: 0 },
];

const known = users.filter((user) => user.age);
const unknown = users.filter((user) => !user.age);

console.log(known.length, unknown.length);
1 2

filter() を2回書く方法との違い

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
2 1
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
[ 2, 4 ] [ 1, 3, 5 ]

結果は同じです。 件数が少なく、条件が単純なら、これで構いません。

違いはここです。

filter() × 2 1回で分ける
走る回数 2 1
条件の書き場所 2か所 1か所
条件が重いとき 2倍かかる そのまま
読みやすさ 短い 関数が1つ要る

問題になるのは条件が2か所にあることです。

いちばんの落とし穴:否定を書き間違える

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
[ [], [] ]
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
[ 'a' ] [ 'b' ]

age0 の人が「年齢が分からない」側に入りました。 0 は偽として扱われるからです。

しかも合計は3件のままなので、数を見ても気づけません。

条件を直すなら、2か所とも直す必要があります。

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
[ 1, 3 ] [ 'だめ' ]
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
{ A: [ 95 ], B: [ 72, 88 ], C: [ 48 ] }

片方だけ直すと、どちらにも入らない要素や、両方に入る要素が出ます。 分ける関数に渡す形なら、条件は1つしかないのでずれようがありません

!= nullnullundefined の両方に当たる、数少ない「緩い比較を使ってよい」書き方です。なぜ == ではなく === を使うのか

reduce() で書く形

結果は同じですが、勧めません。 1件ごとに配列を作り直しているので、件数が増えると急に遅くなります。 読むのにも時間がかかります。

Array.prototype.reduce()

空の配列を渡したとき

空が2つ返ります。 特別扱いは要りません。

受け取った側で「片方が空かどうか」を見るときは、 every() が空配列で true になることに注意してください。 → every() と some()

条件に名前を付ける

分ける関数を使ういちばんの利点は、条件に名前が付くことです。

isAdult を直したいときに、直す場所は1か所です。 filter() を2回書いていると、否定側も一緒に直さなければなりません。

非同期の結果を分ける

成功と失敗に分ける形は、実務でいちばんよく使います。

Promise.allSettled() は、1つ失敗しても最後まで走りますPromise.all() だと最初の失敗で止まるので、この分け方はできません。 → 複数の非同期処理を同時に走らせる

ここは条件が status の一致なので、書き間違えても fulfilledrejected のどちらにも入らないだけです。合計が合わなくなるので、否定の書き間違いより気づきやすくなります。

3つ以上に分けたいとき

2つで足りないなら、分けるのではなくまとめるほうに切り替えます。

配列をキーごとにまとめる(グループ化)

まとめ

  • 条件は1か所だけ書く。 分ける関数を1つ用意すれば済む
  • filter() を2回でも結果は同じ。ただし条件が2か所に散る
  • 否定を書き間違えると、合計が合ったまま中身がずれる
  • 0 や空文字を条件にそのまま使わない。!= null で書く
  • reduce() で書けるが、毎回配列を作り直すので勧めない
  • 条件に名前を付けると、直す場所が1か所で済む
  • 3つ以上なら Object.groupBy()

この記事の根拠

  1. Array.prototype.filter — ECMAScript® 2026 Language Specificationtc39.es
  2. Array.prototype.reduce — ECMAScript® 2026 Language Specificationtc39.es

掲載しているコード例は、公開前に読み手が押したときに動くのと同じもので実行して出力を突き合わせています。結果はリポジトリに残しています。

このページの原文(Markdown)