関数型プログラミング

map(マップ関数) まっぷ

高階関数関数型プログラミングコレクション操作イテレータラムダ式配列操作
mapについて教えて

簡単に言うとこんな感じ!

map は「リストの全員に同じ処理をまとめてやらせる係」だよ!たとえば「社員リスト全員の名前を大文字にして」とか「価格一覧を全部1.1倍にして」みたいな作業を、ループをいちいち書かずにスッキリ1行でこなせる魔法の関数なんだ!


mapとは

mapコレクション(配列やリストなど)の各要素に対して、ある関数を適用し、その結果を新しいコレクションとして返す高階関数です。「高階関数」とは、関数を引数として受け取れる関数のこと。map は「何をするか(処理内容)」を関数として受け取り、「全要素に繰り返し適用する」という仕組みを担います。

ビジネスの場面でイメージすると、「商品リストの価格を全部10%増し」「ユーザー名一覧をすべて大文字に変換」といった「全員に同じ加工を施す」操作が、forループを書かずに宣言的(= “何をしたいか”を直接書くスタイル)に表現できます。これにより、コードの意図が一目でわかりやすくなるのが最大のメリットです。

map関数型プログラミングの三大コンビネータ(map / filter / reduce)の一角を担い、JavaScriptやPython、Scala、Haskellなど現代のほぼすべての言語に組み込まれています。


mapの構造と動き

基本的な動作イメージ

入力リスト        関数 f          出力リスト
[ 1, 2, 3, 4 ]  ──f(x) = x*2──▶  [ 2, 4, 6, 8 ]
  ↑ ↑ ↑ ↑                          ↑ ↑ ↑ ↑
  各要素に f を適用                 変換後の新しいリスト

ポイントは元のリストを変更せず、新しいリストを返すところ。これを「イミュータブル(不変)」な操作といいます。

各言語での書き比べ

言語記述例備考
JavaScript[1,2,3].map(x => x * 2)Array.prototype.mapメソッド
Pythonlist(map(lambda x: x*2, [1,2,3]))組み込み関数 or リスト内包表記
Ruby`[1,2,3].map {x
ScalaList(1,2,3).map(x => x * 2)コレクション全般に対応
Haskellmap (*2) [1,2,3]最も純粋な関数型スタイル

覚え方:「地図(map)に変換を重ねるイメージ」

地図(map)は「ある座標を別の座標に対応させる」もの。数学でも「写像(mapping)」と言い、入力空間の各点を出力空間の点に変換する意味で map という名が使われています。「元の値 → 変換後の値」を1対1で対応させるイメージです。

mapの3つの性質

性質内容具体例
全要素適用リストの要素すべてに関数を適用する1件も飛ばさない
要素数不変入力と出力のリスト長は同じ3要素→3要素
元データ不変元のリストを書き換えない新しいリストを返す

歴史と背景

  • 1950年代 — LISPが登場し、関数をデータとして扱う「高階関数」の概念が生まれる。mapcar(後のmap)がリスト処理の核心的な操作として確立
  • 1970〜80年代 — ML・Haskellなど静的型付き関数型言語が発展し、型安全なmapが普及。map :: (a -> b) -> [a] -> [b] という型シグネチャが定式化される
  • 1990年代 — Pythonがmap()を組み込み関数として採用。手続き型言語にも関数型の概念が流入し始める
  • 2000年代 — RubyのEnumerable#map、ScalaのコレクションAPIなど、オブジェクト指向言語がメソッドとしてmapを取り込む
  • 2011年 — JavaScriptにES5でArray.prototype.mapが標準化。フロントエンド開発で爆発的に普及
  • 2015年以降 — JavaのStream API、C#のLINQなど、エンタープライズ言語にもmap相当の操作が本格導入。「関数型スタイル」が業務系開発の標準になっていく

filter・reduceとの関係:三大コンビネータ

map は単体でも強力ですが、filterreduce と組み合わせることで真価を発揮します。この3つは「関数型プログラミングの三種の神器」とも呼ばれます。

関数やること例えると
map全要素を変換して新リストを作る全員の給料を1.1倍にする
filter条件を満たす要素だけ残す給料30万以上の人だけ抽出
reduce全要素をまとめて1つの値にする給料の合計を計算する

3つを組み合わせたパイプライン

社員リスト

  ▼ filter(在籍中の人だけ)
  │  [ {name:"田中", active:true}, {name:"山田", active:false}, ... ]
  │        ↓ 条件に合う人だけ残す
  ▼ map(名前だけ取り出す)
  │  [ "田中", "佐藤", "鈴木" ]
  │        ↓ 変換
  ▼ reduce(カンマで連結)
     "田中, 佐藤, 鈴木"

SVG図解:mapの変換フロー

map の変換フロー(例:x => x * 2) 1 入力 2 入力 3 入力 f(x) = x × 2 変換関数 2 出力 4 出力 6 出力 [ 1, 2, 3 ] [ 2, 4, 6 ]

関連用語