配列メソッド
map と filter を中心に、React で必須の配列操作を PHP の array 関数と比較しながら学びます。
このチャプターで学ぶこと
- .map() で配列を変換できる
- .filter() で配列を絞り込める
- メソッドチェーンで複数の操作を組み合わせられる
- 不変性(イミュータビリティ)の考え方を理解できる
配列メソッド
Reactを書くとき、配列操作は日常的な作業です。商品リストの表示、タスクのフィルタリング、カートの合計金額の計算——あらゆる場面で使います。
このチャプターでは .map() と .filter() を重点的に学びます。この2つだけでReact開発の配列操作の大半をカバーできます。
PHPの配列関数との比較
まず大まかな対応関係を把握しましょう。
| PHP | JavaScript | 用途 |
|---|---|---|
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: "山田 太郎" }, ...]
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() はキーを保持するため、インデックスが飛ぶことがあります([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); // 13000reduce は強力ですが、複雑になりがちです。多くのケースでは .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が変わったことを検知して画面を更新します。.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操作) を学びます。