JavaScript 配列の実践:filter・map・reduce のチェーン活用例

スポンサーリンク

JavaScript 配列の実践:filter・map・reduce のチェーン活用例

filtermapreduce は単体でも使いますが、メソッドチェーンで組み合わせると複雑な処理を簡潔に書けます。実際のコードでよく登場するパターンをまとめます。


カートの合計金額を計算する

在庫あり・数量1以上の商品だけ対象にして合計金額を出す例です。

const cart = [
  { name: 'apple',  price: 100, qty: 2, inStock: true },
  { name: 'banana', price:  80, qty: 0, inStock: false }, // 数量0
  { name: 'cherry', price: 200, qty: 1, inStock: true },
  { name: 'grape',  price: 300, qty: 1, inStock: false }, // 在庫なし
]

const total = cart
  .filter((item) => item.inStock && item.qty > 0) // 有効な商品だけ絞り込む
  .map((item) => item.price * item.qty)           // 小計に変換
  .reduce((sum, amount) => sum + amount, 0)       // 合計
// → 400(apple: 200 + cherry: 200)

filtermapreduce は「絞り込む → 変換する → 集計する」という流れで、最もよく登場するパターンです。


API レスポンスを整形する

API から返ってきたデータを「有効なもの」だけに絞り、必要なフィールドだけに整形してソートする例です。

const users = [
  { id: 1, name: 'Alice', role: 'admin', deletedAt: null },
  { id: 2, name: 'Bob',   role: 'user',  deletedAt: '2024-01-01' }, // 削除済み
  { id: 3, name: 'Carol', role: 'admin', deletedAt: null },
  { id: 4, name: 'Dave',  role: 'user',  deletedAt: null },
]

const activeAdmins = users
  .filter((user) => user.role === 'admin' && !user.deletedAt) // 有効な管理者だけ
  .map((user) => ({ id: user.id, name: user.name }))          // 必要なフィールドだけ
  .sort((a, b) => a.name.localeCompare(b.name))               // 名前順
// → [{ id: 1, name: 'Alice' }, { id: 3, name: 'Carol' }]

タグの出現ランキングを作る

複数の記事・商品に付いたタグを集計して、出現回数順のランキングを作る例です。

const articles = [
  { title: '記事A', tags: ['js', 'react', 'typescript'] },
  { title: '記事B', tags: ['js', 'node'] },
  { title: '記事C', tags: ['react', 'typescript'] },
  { title: '記事D', tags: ['js', 'react'] },
]

const tagRanking = articles
  .flatMap((article) => article.tags)          // タグを1つの配列に展開
  .reduce((acc, tag) => {
    acc[tag] = (acc[tag] || 0) + 1
    return acc
  }, {})                                        // { js: 3, react: 3, typescript: 2, node: 1 }

const top3 = Object.entries(tagRanking)
  .sort(([, a], [, b]) => b - a)               // 出現回数の降順
  .slice(0, 3)                                  // 上位3件
  .map(([tag, count]) => ({ tag, count }))     // 整形
// → [{ tag: 'js', count: 3 }, { tag: 'react', count: 3 }, { tag: 'typescript', count: 2 }]

ユーザー別の売上合計を出す

注文データをユーザーごとにまとめて、売上の多い順に並べる例です。

const orders = [
  { user: 'Alice', amount: 1000 },
  { user: 'Bob',   amount:  500 },
  { user: 'Alice', amount: 2000 },
  { user: 'Carol', amount: 1500 },
  { user: 'Bob',   amount:  800 },
]

const ranking = Object.entries(
  orders.reduce((acc, { user, amount }) => {
    acc[user] = (acc[user] || 0) + amount
    return acc
  }, {})                                        // { Alice: 3000, Bob: 1300, Carol: 1500 }
)
  .map(([user, total]) => ({ user, total }))   // 配列のオブジェクトに整形
  .sort((a, b) => b.total - a.total)           // 売上降順
// → [{ user: 'Alice', total: 3000 }, { user: 'Carol', total: 1500 }, ...]

複数条件の検索フィルタリング

検索クエリ・価格上限・カテゴリで絞り込む例です。条件ごとに filter を分けると読みやすくなります。

const products = [
  { name: 'Apple juice', price: 200, category: 'drink' },
  { name: 'Apple pie',   price: 600, category: 'food' },
  { name: 'Green apple', price: 150, category: 'fruit' },
  { name: 'Apple watch', price: 50000, category: 'gadget' },
]

const query    = 'apple'
const maxPrice = 500
const category = 'fruit'

// 条件ごとに filter を分けると意図が読みやすい
const results = products
  .filter((p) => p.name.toLowerCase().includes(query))
  .filter((p) => p.price <= maxPrice)
  .filter((p) => !category || p.category === category)
  .sort((a, b) => a.price - b.price)
// → [{ name: 'Green apple', price: 150, category: 'fruit' }]

チェーンを書くときのポイント

// ❌ 読みにくい:何をしているか追いづらい
const result = data.filter(x => x.active).map(x => x.value * 2).reduce((a, b) => a + b, 0)

// ✅ 読みやすい:処理ごとに改行してコメントを添える
const result = data
  .filter((x) => x.active)        // 有効なものだけ
  .map((x) => x.value * 2)        // 2倍に変換
  .reduce((sum, v) => sum + v, 0) // 合計
  • filtermapreduce の順が基本(絞り込んでから変換・集計)
  • map してから filter すると不要な変換が走るため、filter を先に
  • 中間結果を確認したいときは一時変数に切り出す

まとめ

パターン チェーン
有効なものを集計する filtermapreduce
データを整形してソートする filtermapsort
ネストした配列を集計する flatMapreduce / Object.entries
グループ別に集計する reduce(グループ化)→ Object.entriessort

filtermapreduce 各メソッドの詳細は以下を参照してください。 - 「JavaScript 配列の絞り込み:filter・find・some の使い方」 - 「JavaScript 配列の変換・集計:map・reduce・flatMap の使い方