map で全要素を変換
map で全要素を変換 とは
map 関数でリストの全要素を変換する方法を学びます。本レッスンでは、map で全要素を変換 の基本から実際の使いどころまでを整理し、現場で迷わず使える形に落とし込みます。
map で全要素を変換
リストの全要素に同じ処理を適用したいとき、Python には便利な高階関数 map があります。for ループで 1 つずつ処理しても良いのですが、map を使うと「何をどう変換するのか」が一目で分かるコードになります。map は関数型プログラミングの世界からやってきた、シンプルで強力な道具です。
mapは「リストの形は保ったまま、中身だけを変換する」操作です。各要素を 1 つずつ取り出して、関数を通して、新しいリストにまとめ直します。
文法
map(関数, イテラブル) という形で書きます。
Python
nums = [1, 2, 3, 4]
result = map(lambda x: x * 2, nums)
print(list(result))map の結果は map オブジェクト (iterator) という特殊な形なので、list() で囲んで リスト に変換します。出力は [2, 4, 6, 8] です。
def で定義した関数も渡せます。
Python
def square(x):
return x * x
result = list(map(square, [1, 2, 3]))
print(result)for ループとの比較
まず、for ループで書いた場合と比べてみます。
Python
# for ループ版
nums = [1, 2, 3, 4]
result = []
for n in nums:
result.append(n * 2)これを map で書くと次のとおりです。
Python
# map 版
nums = [1, 2, 3, 4]
result = list(map(lambda x: x * 2, nums))for 版は「ループを回して append する」というプロセス重視の書き方、map 版は「全要素を 2 倍する」という結果重視の書き方です。後者は意図が読み取りやすく、ミスも減ります。
map vs リスト内包表記
Python には map とよく似た機能を持つ リスト内包表記 (list comprehension) もあります。
Python
result = [x * 2 for x in nums]Python コミュニティでは、シンプルな変換ならリスト内包表記の方が Pythonic (Python らしい) とされることが多いです。map は 既存の関数をそのまま使うとき に特に便利です。
Python
strings = ["1", "2", "3"]
result = list(map(int, strings))
print(result)文字列のリストを int 関数で一気に整数に変換しています。これはリスト内包表記より map の方がスッキリ書けます。
どちらを使うかは好みもありますが「既存の関数を渡すだけなら map」「式を書きたいなら内包表記」と覚えておくと選びやすくなります。
動きを追ってみる
map の処理を図にしてみます。
各要素を 1 つずつ「変換器」に通して、新しいリストへ積み上げていきます。元のリストは変更されません。
複数のイテラブルを渡す
map には複数のリストを渡すこともできます。その場合、関数は複数の引数を取ります。
Python
a = [1, 2, 3]
b = [10, 20, 30]
result = list(map(lambda x, y: x + y, a, b))
print(result)結果は [11, 22, 33] です。a と b の対応する要素同士が lambda に渡されます。
よくある間違い
list()で囲み忘れてmapオブジェクトのまま使う- 関数を
func()のように呼び出して渡してしまう - 元のリストが変わると思ってしまう (
mapは新しいリストを作る)
Python
bad = map(lambda x: x * 2, [1, 2, 3])
print(bad)これは <map object at 0x...> のように表示されてしまいます。list(bad) で囲んでようやくリストとして使えます。
mapの結果は イテレータ (iterator) です。1 回しか使えないので、複数回使いたいなら早めにlistに変換するのが安全です。
実用シーン
map がよく使われるのは、文字列処理やデータ整形です。CSV から読み込んだ文字列を一括で int に変換するときなど、list(map(int, row)) のような書き方は定番です。strip でホワイトスペースを取るときも list(map(str.strip, lines)) と書けます。コードが意図を雄弁に語ってくれます。
やってみよう
それでは、整数のリスト arr を受け取って、全要素を 2 倍にした新しいリストを返す関数 double_list を map と lambda を使って書いてみましょう。list(map(lambda x: x * 2, arr)) の形が答えです。テストでは double_list([1, 2, 3]) のような形で呼び出されます。
よくある質問
Q. map は for ループより速いですか?
A. CPython では大差ない場合が多いですが、map(int, strs) のように組み込み関数を渡すと内包表記より僅かに速いことがあります。JavaScript でも明確な差は出にくいため、可読性で選ぶのが基本で、配列が巨大な場合のみベンチマークしましょう。
Q. map と forEach の違いは?
A. map は新しい配列を返し、forEach は副作用を起こすだけで戻り値が undefined です。「変換後の配列を作る」なら map、「ログ出力や DOM 更新だけ」なら forEach を使うと意図が伝わります。途中で抜けたい場合は for...of + break を選びましょう。
Q. map の戻り値が思った形になりません
A. map は元と同じ長さの配列を返します。条件で要素数を変えたいなら filter を先にかけるか、flatMap で空配列 [] を返した分を平らにできます。インデックスが必要なら map((v, i) => ...) のように第 2 引数で受け取ってください。
次のレッスン
次は filter で要素を絞り込む で、map 関数でリストの全要素を変換する方法を学びます を学びます。
事前確認 — 進む前に次の 3 つができることを確認しましょう。
- map の要点を自分の言葉で説明できる
- このレッスンの最小コード (または操作手順) を見ずに書ける
- 練習問題やクイズで間違えた箇所を読み直して理解した
理解度チェック (30 秒)
Q. map とは何か、1 文で説明してください。
A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。
関連レッスン
要件
- map と lambda を組み合わせて使う
- 結果を list で囲んでリストとして返す
- for ループは使わない
入出力例
test-cases.txt
double_list([1,2,3]) → [2,4,6]
double_list([]) → []
double_list([-1,0,1]) → [-2,0,2]
double_list([5]) → [10]