filter関数と同じく、いろんなプログラミング言語で実装されている機能の一つにmap(マップ)というものがあります。これはリストのようなオブジェクトに含まれる各要素に対して、何かしらの変換を行った別のオブジェクトを作る操作になります。
やはりfilterと同じく、Pythonだけでなく他の様々な言語でも役に立つ機能です。是非とも使ってみてください!この記事では
- そもそもmapとは何なのだろう
- mapでシーケンスの各要素に同じ処理をかける方法
などの基本的におさえておきたい内容から、リスト内包表記との比較などのPythonを勉強している方が気になる内容についても説明していきます。それでは見ていきましょう!
※ この記事のコードはPython 3.7で動作確認しました。
本記事を読む前に、Pythonがどんなプログラミング言語なのかをおさらいしておきたい人は次の記事を参考にしてください。
→ Pythonとは?特徴やできること、活用例をわかりやすく簡単に解説
なお、その他のPythonの記事についてはこちらにまとめています。
Pythonのmapとは
map関数はリストのような複数の要素をもったオブジェクト(これをシーケンスと呼びましたね)と関数を引数として受け取ります。そしてシーケンスの各要素を、受け取った関数に渡して実行してくれます。このように関数を受け取る関数や関数を返す関数を高階関数と呼びます。
これは関数型言語でよく使われる機能です。同じ高階関数として有名なものにfilterがあります。これについては以下の記事で解説しています。
map関数の使い方は、filter関数を使ったことのある人ならば馴染みやすい形です。
map(function, sequence_object)
第一引数が関数(またはlambda式)、第二引数がシーケンスです。
Pythonのmapの使い方
実際にコードを実行しながらmap関数の使い方を見ていきましょう。ここでは簡単に、受け取った数字を二乗する例を使います。
original_list = list(range(10)) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] mapped_list = map(lambda x: x**2, original_list) print(list(mapped_list))
実行結果
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
この例では0から9までの数字を格納したリスト(original_list)を作り、与えられた値を二乗するラムダ式でmapしています。結果を見るとうまくいっていることがわかりますね。このようにmap関数を用いると、一つの要素に対する処理をリスト全体に対して行ってくれます。
ただし、Python 3.Xのmap関数の返り値はmap型のオブジェクトになります。ですのでそのままでは中の要素を見ることができません。もしもここで、map関数の返り値をそのまま表示してやると
<map at 0x2616fdee160>
のように表示されます。このように欲しい結果とは異なる表示が得られた場合は、help関数を使ってオブジェクトの詳細を確認して見ることをおすすめします。
print(help(mapped_list))
実行結果
Help on map object: class map(object) | map(func, *iterables) --> map object | | Make an iterator that computes the function using arguments from | each of the iterables. Stops when the shortest iterable is exhausted. # 以下mapクラスに関する説明が続きます。
そのためここではmap関数の返り値をlist関数を使ってlist型オブジェクトに変換しているんですね。では次に、lambda式ではない普通の関数をmap関数の引数に渡してみましょう。例としてここではFizz Buzzをやってみます。
Fizz Buzzは
- 3で割り切れる場合は「Fizz」
- 5で割り切れる場合は「Buzz」
- 3と5の両方で割り切れる場合は「Fizz Buzz」
を数字の代わりに表示する簡単な問題です。
def fizz_buzz(number): if number % 3 == 0 and number % 5 == 0: return "Fizz Buzz" elif number % 3 == 0: return "Fizz" elif number % 5 == 0: return "Buzz" else: return number for ans in map(fizz_buzz, range(20)): print(ans)
実行結果
Fizz Buzz 1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 Fizz Buzz 16 17 Fizz 19
このように、if文が入っている関数であってもちゃんと動作します。また、mapの第二引数はrange関数をそのまま渡しても大丈夫なんです。
ただし注意してください。このfizz_buzz関数がもしも何も値を返さない事があった場合、mapの返り値にはNoneが代わりに収まります。つまり最後のelse節がなかった場合、実行結果は以下のようになります。
Fizz Buzz None None Fizz None Buzz Fizz None None Fizz Buzz None Fizz None None Fizz Buzz None None Fizz None
リスト内包表記との比較
さて、map関数と同様の事はリスト内包表記によって実装することができます。リスト内包表記の使い方については以下の記事で詳しく解説しているので、是非読んでみてください。
先程のFizz Buzzのmap関数をリスト内包表記で実装してみましょう。
result = [fizz_buzz(x) for x in range(20)]
これで先程と同じ結果が得られます。リスト内包表記は複雑になると読みづらくなりやすいですが、このくらいのシンプルさであれば気になりませんね。
ここではリスト内包表記とmap関数の内部実装については触れませんが、これらの実行速度は一概にどちらが速いとは断言できません。map関数を使った使い方とリスト内包表記、どちらがお好みだったでしょうか。
このままPythonを学び続けて大丈夫?
なぜPythonを学ぶのか?
あなたがPythonを学ぶ理由は何でしょうか?
- Pythonが人気だからとりあえず学んでいる
- AIや機械学習の分野に興味があるから
Pythonは初心者向けの言語と言われています。その理由としてシンプルでわかりやすい構文や、実用的なライブラリが豊富なことが挙げられ、実際に学びやすい言語です。
しかし、もしあなたが機械学習に興味があって、とくに知識も無いまま学習を進めると、挫折する可能性が高いと言えます。
機械学習の分野はプログラミング以外にも、専門的な知識や数学の知識も必要になります。ただなんとなく学習していると早い段階でつまづきやすく、そのまま挫折してしまうなんてことも…。
そのため、挫折しないためには、
- 最適な学習環境を用意する
- 必要なライブラリ・ツールを導入する
- わからないことを質問できるメンターを見つける
などが必要になります。
効率よく学びたいなら、無料カウンセリングがおすすめ
まだまだ知りたいことがたくさんある!
もっと詳しくPythonについて知りたい!
といった悩みや願望を持っている方は、弊社「侍エンジニア」をご利用下さい。
侍エンジニアでは、
- 現役エンジニアによるマンツーマンレッスン
- キャリアアドバイザーによる転職・就職支援
- 業界屈指のフリーランス・起業サポート
を受けることができます。
業界屈指のコンサルタントから、効率的な学習方法や仕事獲得術、今後のキャリアまでさまざまな疑問を相談してみませんか?遠方の方でもオンラインで受講できます!お気軽に受講下さい。
侍エンジニア無料カウンセリングを受ける
まとめ
この記事ではPythonのmap関数について紹介しました。map関数はシーケンスの構成要素全てに対して関数を適用してくれる高階関数です。
他にforループを置き換えることので出来る関数として、map、filter、reduceなどの他の高階関数があります。これらを使いこなすことで読みやすく直感的なプログラミングができるようになります。
是非覚えて使ってみてください!