Chapter 02

配列メソッド

map と filter を中心に、React で必須の配列操作を PHP の array 関数と比較しながら学びます。

25 min

このチャプターで学ぶこと

  • .map() で配列を変換できる
  • .filter() で配列を絞り込める
  • メソッドチェーンで複数の操作を組み合わせられる
  • 不変性(イミュータビリティ)の考え方を理解できる

配列メソッド

Reactを書くとき、配列操作は日常的な作業です。商品リストの表示、タスクのフィルタリング、カートの合計金額の計算——あらゆる場面で使います。

このチャプターでは .map().filter() を重点的に学びます。この2つだけでReact開発の配列操作の大半をカバーできます。

PHPの配列関数との比較

まず大まかな対応関係を把握しましょう。

PHPJavaScript用途
array_map().map()各要素を変換して新しい配列を作る
array_filter().filter()条件に合う要素だけを残す
array_search().find()条件に合う要素を探す
array_reduce().reduce()配列を単一の値に集約する

重要な違い: PHPでは array_map($callback, $array) のように関数の引数として配列を渡します。JavaScriptでは array.map(callback) のように 配列自身がメソッドを持っています。この違いにより、メソッドを . でつなぐ「メソッドチェーン」が自然に書けます。


.map() — 配列を変換する

.map() は配列の各要素に関数を適用して、同じ要素数の新しい配列を返します。元の配列は変更されません。

<?php
// PHP
$numbers = [1, 2, 3, 4, 5];
$doubled = array_map(fn($n) => $n * 2, $numbers);
// [2, 4, 6, 8, 10]
// JavaScript
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map((n) => n * 2);
// [2, 4, 6, 8, 10]

// 元の配列は変わらない
console.log(numbers); // [1, 2, 3, 4, 5]
console.log(doubled); // [2, 4, 6, 8, 10]

オブジェクトの配列を変換する

実際の開発ではオブジェクトの配列を扱うことが多いです:

const users = [
  { id: 1, firstName: "太郎", lastName: "山田", age: 30 },
  { id: 2, firstName: "花子", lastName: "鈴木", age: 25 },
  { id: 3, firstName: "一郎", lastName: "田中", age: 35 },
];

// フルネームの配列を作る
const fullNames = users.map((user) => `${user.lastName} ${user.firstName}`);
console.log(fullNames);
// ["山田 太郎", "鈴木 花子", "田中 一郎"]

// 必要なプロパティだけを持つオブジェクトに変換
const simplified = users.map((user) => ({
  id: user.id,
  name: `${user.lastName} ${user.firstName}`,
}));
// [{ id: 1, name: "山田 太郎" }, ...]
💡 map は React で最も重要なメソッドです

ReactでJSXのリストを表示するときは、ほぼ必ず .map() を使います。

// 参考: React ではこう書く(まだ覚えなくてOK)
function ProductList({ products }) {
  return (
    <ul>
      {products.map((product) => (
        <li key={product.id}>
          {product.name}{product.price}
        </li>
      ))}
    </ul>
  );
}

.map() を使いこなせると、ReactのUIをデータから動的に生成できるようになります。


.filter() — 配列を絞り込む

.filter() は条件に合う要素だけを残した新しい配列を返します。

<?php
// PHP
$numbers = [1, 2, 3, 4, 5, 6, 7, 8];
$evens = array_filter($numbers, fn($n) => $n % 2 === 0);
// [2, 4, 6, 8]
// JavaScript
const numbers = [1, 2, 3, 4, 5, 6, 7, 8];
const evens = numbers.filter((n) => n % 2 === 0);
console.log(evens); // [2, 4, 6, 8]

// 元の配列は変わらない
console.log(numbers); // [1, 2, 3, 4, 5, 6, 7, 8]

オブジェクトの配列に適用する

const products = [
  { id: 1, name: "Tシャツ", price: 2500, inStock: true },
  { id: 2, name: "ジーンズ", price: 8000, inStock: false },
  { id: 3, name: "スニーカー", price: 12000, inStock: true },
  { id: 4, name: "サンダル", price: 4000, inStock: true },
];

// 在庫ありの商品だけ
const inStockProducts = products.filter((p) => p.inStock);

// 5000円以下の商品だけ
const affordable = products.filter((p) => p.price <= 5000);

// 条件を組み合わせることもできる
const cheapAndAvailable = products.filter(
  (p) => p.price <= 5000 && p.inStock
);
// [{ id: 1, name: "Tシャツ", ... }, { id: 4, name: "サンダル", ... }]
📝 PHP の array_filter との違い

PHPの array_filter() はキーを保持するため、インデックスが飛ぶことがあります([0 => ..., 2 => ...])。JavaScriptの .filter() は常に0始まりの連番で新しい配列を返します。


その他の便利なメソッド

.map().filter() が配列操作の基本です。以下のメソッドも覚えておくと便利ですが、まずは「こういうものがある」と知っていれば十分です。

.find() — 要素を検索する

条件に合う最初の要素を返します。見つからない場合は undefined です。

const users = [
  { id: 1, name: "山田" },
  { id: 2, name: "鈴木" },
  { id: 3, name: "田中" },
];

const user = users.find((u) => u.id === 2);
console.log(user); // { id: 2, name: "鈴木" }

const notFound = users.find((u) => u.id === 99);
console.log(notFound); // undefined
findIndex / includes の例を見る

.findIndex() は条件に合う要素のインデックスを返します(見つからなければ -1)。.includes() は値が含まれるかを true / false で返します。

const tasks = [
  { id: 1, title: "買い物", done: false },
  { id: 2, title: "掃除", done: true },
];

// インデックスを探す
const index = tasks.findIndex((t) => t.id === 2);
console.log(index); // 1

// 値が含まれるか確認(シンプルな配列向け)
const fruits = ["りんご", "バナナ", "みかん"];
console.log(fruits.includes("バナナ")); // true
console.log(fruits.includes("ぶどう")); // false

.reduce() — 配列を集約する

配列のすべての要素を処理して、一つの値にまとめます。合計の計算などに使います。

const prices = [2500, 8000, 12000];

// 合計を計算
const total = prices.reduce((sum, price) => sum + price, 0);
console.log(total); // 22500
reduce の詳しい使い方を見る

reduce の動きを追ってみましょう:

const numbers = [1, 2, 3, 4, 5];

// reduce(コールバック, 初期値)
const sum = numbers.reduce((total, n) => total + n, 0);
// total=0, n=1 → 1
// total=1, n=2 → 3
// total=3, n=3 → 6
// total=6, n=4 → 10
// total=10, n=5 → 15

// オブジェクト配列の合計
const orders = [
  { product: "Tシャツ", price: 2500, quantity: 2 },
  { product: "ジーンズ", price: 8000, quantity: 1 },
];

const totalAmount = orders.reduce(
  (total, order) => total + order.price * order.quantity,
  0
);
console.log(totalAmount); // 13000

reduce は強力ですが、複雑になりがちです。多くのケースでは .map().filter() の組み合わせで十分です。

.forEach() / .some() / .every()

forEach / some / every の例を見る
// .forEach() — 各要素に処理を実行する(戻り値はない)
const users = [{ name: "山田" }, { name: "鈴木" }];
users.forEach((user) => {
  console.log(`こんにちは、${user.name}さん`);
});
// ※ 新しい配列を作りたい場合は forEach ではなく map を使う

// .some() — 1つでも条件を満たす要素があるか
const products = [
  { name: "Tシャツ", inStock: true },
  { name: "ジーンズ", inStock: false },
];
const hasAnyInStock = products.some((p) => p.inStock);
console.log(hasAnyInStock); // true

// .every() — すべての要素が条件を満たすか
const scores = [85, 92, 78, 95];
const allPassing = scores.every((score) => score >= 70);
console.log(allPassing); // true

.sort() — 配列をソートする

sort の使い方と注意点を見る
// デフォルトは文字列順なので、数値には比較関数が必要
const numbers = [10, 1, 5, 100, 21];
const sorted = [...numbers].sort((a, b) => a - b); // 昇順
console.log(sorted); // [1, 5, 10, 21, 100]

// 降順
const desc = [...numbers].sort((a, b) => b - a);

// オブジェクト配列を価格順に
const products = [
  { name: "バッグ", price: 15000 },
  { name: "Tシャツ", price: 2500 },
];
const byPrice = [...products].sort((a, b) => a.price - b.price);

注意: .sort() は元の配列を直接変更します(破壊的メソッド)。必ず [...arr].sort() のようにコピーしてからソートしてください。Reactでは特に重要です。


メソッドチェーン

配列メソッドは新しい配列を返すため、. でつなげて書けます。これが PHP にはない JavaScript の大きな利点です。

const products = [
  { id: 1, name: "Tシャツ", price: 2500, inStock: true },
  { id: 2, name: "ジーンズ", price: 8000, inStock: false },
  { id: 3, name: "スニーカー", price: 12000, inStock: true },
  { id: 4, name: "サンダル", price: 4000, inStock: true },
  { id: 5, name: "ベルト", price: 3000, inStock: true },
];

// 「在庫あり・5000円未満」の商品名を価格順で取得
const result = products
  .filter((p) => p.inStock)              // 在庫ありでフィルタ
  .filter((p) => p.price < 5000)         // 5000円未満でフィルタ
  .sort((a, b) => a.price - b.price)     // 価格の昇順
  .map((p) => p.name);                   // 名前だけ取り出す

console.log(result); // ["Tシャツ", "ベルト", "サンダル"]

上から下に処理の流れが読めるので、直感的にわかります。


不変性(イミュータビリティ)

Reactを学ぶ前に必ず理解しておきたい概念です。元の配列を変更せず、新しい配列を作るというルールです。

const arr = [1, 2, 3];

// NG:元の配列を変更するメソッド(破壊的)
arr.push(4);      // 元の配列に追加してしまう
arr.splice(1, 1); // 元の配列から削除してしまう

// OK:新しい配列を返すメソッド(非破壊的)
const added = [...arr, 4];                      // 追加
const removed = arr.filter((n) => n !== 2);     // 削除
const updated = arr.map((n) => n === 2 ? 20 : n); // 更新

React でよく使うパターン

// 追加
const newItems = [...items, newItem];

// 削除
const newItems = items.filter((item) => item.id !== targetId);

// 更新
const newItems = items.map((item) =>
  item.id === targetId ? { ...item, done: true } : item
);
⚠️ Reactではstateを直接変更してはいけません

Reactはstateが変わったことを検知して画面を更新します。.push() のように元の配列を直接変更すると、Reactは変化を検知できません。必ず新しい配列を作って渡してください。

この「直接変更しない」という原則を**イミュータビリティ(不変性)**と言います。


✍ やってみよう:メソッドチェーンで商品を操作する

以下の商品データを使って、メソッドチェーンで問題を解いてください。

const products = [
  { id: 1, name: "Tシャツ", price: 1500, category: "衣類", inStock: true },
  { id: 2, name: "ポロシャツ", price: 3500, category: "衣類", inStock: true },
  { id: 3, name: "ジーンズ", price: 8000, category: "衣類", inStock: false },
  { id: 4, name: "スニーカー", price: 9800, category: "", inStock: true },
  { id: 5, name: "サンダル", price: 2800, category: "", inStock: true },
  { id: 6, name: "ベルト", price: 2200, category: "小物", inStock: true },
];

問題: 在庫あり かつ 3000円未満の商品を、価格の昇順に並べて、名前だけの配列を取得してください。

期待する結果:["Tシャツ", "ベルト", "サンダル"]

ヒント: .filter().filter().sort().map() の順でチェーンします。


解答例:

const result = products
  .filter((p) => p.inStock)
  .filter((p) => p.price < 3000)
  .sort((a, b) => a.price - b.price)
  .map((p) => p.name);

console.log(result); // ["Tシャツ", "ベルト", "サンダル"]

まとめ

このチャプターで学んだ配列メソッドの一覧です。まずは map と filter を使いこなせれば十分です。

メソッド用途戻り値破壊的か
.map()各要素を変換新しい配列非破壊的
.filter()条件で絞り込み新しい配列非破壊的
.find()条件に合う最初の要素要素 or undefined非破壊的
.reduce()配列を一つの値に集約任意の値非破壊的
.forEach()各要素に処理を実行undefined非破壊的
.some()1つでも条件を満たすかtrue / false非破壊的
.every()すべてが条件を満たすかtrue / false非破壊的
.sort()ソート元の配列破壊的

次のチャプターでは、JavaScript から HTML を操作する方法(DOM操作) を学びます。