---
type: how-to
language: javascript
slug: array/partition
title: "配列を条件で2つに分ける"
title_tag: "JavaScript 配列を条件で分割する — partition の書き方"
summary: >
  条件に合うものと合わないものを、1回のループで2つの配列に分けます。
  filter() を2回書く方法との違い、条件の否定を書き間違えて件数が合わなくなる罠まで確かめます。
description: >
  filter() を2回書くと条件が2か所に散り、否定を書き間違えたときに合計が合わなくなります。
  1回のループで分ける書き方と、その差が出る場面を実行して確かめられます。
status: published
difficulty: 2
minutes: 7

versions:
  verified: "Node 22.22.3"
  since: "ES2015"
  deprecated: null
  removed: null

sources:
  - title: "Array.prototype.filter — ECMAScript® 2026 Language Specification"
    url: "https://tc39.es/ecma262/#sec-array.prototype.filter"
  - title: "Array.prototype.reduce — ECMAScript® 2026 Language Specification"
    url: "https://tc39.es/ecma262/#sec-array.prototype.reduce"

terms: [分割, 述語, 畳み込み]

links:
  related:
    - javascript/reference/array/filter
    - javascript/reference/array/every-some
    - javascript/how-to/array/group

content_updated_at: 2026-09-08
published_at: 2026-09-08
---

## 答え

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

```js run
function partition(list, test) {
  const yes = [];
  const no = [];

  for (const item of list) {
    (test(item) ? yes : no).push(item);
  }

  return [yes, no];
}

console.log(partition([1, 2, 3, 4, 5], (n) => n % 2 === 0));
```
```output
[ [ 2, 4 ], [ 1, 3, 5 ] ]
```

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

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

```js run
function partition(list, test) {
  const yes = [];
  const no = [];

  for (const item of list) {
    (test(item) ? yes : no).push(item);
  }

  return [yes, no];
}

const [passed, failed] = partition(
  [{ id: 1, ok: true }, { id: 2, ok: false }],
  (item) => item.ok,
);

console.log(passed);
console.log(failed);
```
```output
[ { id: 1, ok: true } ]
[ { id: 2, ok: false } ]
```

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

```js run
const nums = [1, 2, 3, 4, 5];

const even = nums.filter((n) => n % 2 === 0);
const odd = nums.filter((n) => n % 2 !== 0);

console.log(even, odd);
```
```output
[ 2, 4 ] [ 1, 3, 5 ]
```

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

違いはここです。

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

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

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

```js bad
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);
```
```output
1 2
```

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

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

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

```js run
const users = [
  { name: 'a', age: 20 },
  { name: 'b', age: null },
  { name: 'c', age: 0 },
];

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

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

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

[dim:`!= null` は `null` と `undefined` の両方に当たる、数少ない「緩い比較を使ってよい」書き方です。]
→ [なぜ == ではなく === を使うのか](/ja/javascript/why/strict-equality/)

## `reduce()` で書く形

```js run
const [even, odd] = [1, 2, 3, 4, 5].reduce(
  ([yes, no], n) => (n % 2 === 0 ? [[...yes, n], no] : [yes, [...no, n]]),
  [[], []],
);

console.log(even, odd);
```
```output
[ 2, 4 ] [ 1, 3, 5 ]
```

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

→ [Array.prototype.reduce()](/ja/javascript/reference/array/reduce/)

## 空の配列を渡したとき

```js run
function partition(list, test) {
  const yes = [];
  const no = [];

  for (const item of list) {
    (test(item) ? yes : no).push(item);
  }

  return [yes, no];
}

console.log(partition([], (n) => n > 0));
```
```output
[ [], [] ]
```

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

受け取った側で「片方が空かどうか」を見るときは、
[bad:`every()` が空配列で true になる]ことに注意してください。
→ [every() と some()](/ja/javascript/reference/array/every-some/)

## 条件に名前を付ける

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

```js run
const isAdult = (user) => user.age >= 18;

function partition(list, test) {
  const yes = [];
  const no = [];

  for (const item of list) {
    (test(item) ? yes : no).push(item);
  }

  return [yes, no];
}

const [adults, minors] = partition(
  [{ name: 'a', age: 20 }, { name: 'b', age: 10 }],
  isAdult,
);

console.log(adults.map((user) => user.name), minors.map((user) => user.name));
```
```output
[ 'a' ] [ 'b' ]
```

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

## 非同期の結果を分ける

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

```js run
const results = await Promise.allSettled([
  Promise.resolve(1),
  Promise.reject(new Error('だめ')),
  Promise.resolve(3),
]);

const succeeded = results.filter((r) => r.status === 'fulfilled').map((r) => r.value);
const failed = results.filter((r) => r.status === 'rejected').map((r) => r.reason.message);

console.log(succeeded);
console.log(failed);
```
```output
[ 1, 3 ]
[ 'だめ' ]
```

`Promise.allSettled()` は、[key:1つ失敗しても最後まで走ります]。
`Promise.all()` だと最初の失敗で止まるので、この分け方はできません。
→ [複数の非同期処理を同時に走らせる](/ja/javascript/how-to/async/parallel/)

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

## 3つ以上に分けたいとき

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

```js run
const scores = [95, 72, 48, 88];

const grouped = Object.groupBy(scores, (n) => {
  if (n >= 90) return 'A';
  if (n >= 70) return 'B';
  return 'C';
});

console.log(grouped);
```
```output
{ A: [ 95 ], B: [ 72, 88 ], C: [ 48 ] }
```

→ [配列をキーごとにまとめる（グループ化）](/ja/javascript/how-to/array/group/)

## まとめ

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