お役立ち情報

Pythonの高階関数map/filterの便利な使い方

pythonのmapとfilterについて

Pythonの高階関数のなかで特に利便性が高く実際のシステム開発現場でも使用頻度が高いものに、mapとfilterがあります。そこでこのページでは、mapとfilterに焦点を当てて解説を進めます。

ちなみにmapもfilterも他のプログラミング言語でも出てくる概念で、コードもそのまま同じ言語もあれば、コード自体は違っても使い方はまったく同じ関数が存在する言語もあります。

いずれにしても理解しておくことでPythonだけでなく他の言語も含めたプログラミングスキル全般がアップする内容なので、ぜひとも押さえておいてください。

Python関連記事

mapの概念と基本的な使い方

まずはmapについて説明しつつ、サンプルコードを紹介していきます。mapとは、たとえばlistのように複数の値を持ったオブジェクトの各要素に対し、順次処理を行うことのできる関数です。順次実行するのでループ処理を記述する必要等はありません。

言葉による説明だけだとわかりにくいので、さっそくサンプルコードを見ていきましょう。宣言部分等は割愛します。

before_list = list(range(10)) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
after_list = map(lambda x: x*2, before_list)
print(list(after_list))

上記のソースコードを実行すると、以下のようにコンソール出力されます。

[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

まずbefore_listに処理実行前の値が入っているのですが、これをmapの第二引数に設定します。そして、mapの第一引数にはlambda式(処理内容)を記述しています。第二引数に設定したオブジェクトの各要素に対して順次第一引数の処理を実行していくため、最終的にすべての要素が倍になってafter_listに格納されました。

一応map関数の公式を記載しておくと以下のようになります。

map(function, sequence_object)

公式を覚えなくても、上記のサンプルコードの処理概要を把握しておけば問題ありません。また、mapの処理とまったく同じ内容をlistの内包表記で実装することが可能です。具体的には以下のサンプルコードのようになります。

before_list = list(range(10)) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
after_list = [x for x in before_list x*2]
print(after_list)

上記のソースコードを実行すると、以下のようにコンソール出力されます。

[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

まったく同じ結果になりました。コードのシンプルさで言えばどちらもそれほど変わらないのですが、おそらくmapを使用した方が直感的に理解しやすいかと思います。次に説明するfilterでも紹介しますが、filterと同じことをlistの内包表記で実装することも可能です。

listの内包表記はコードが直感的にわかりにくいだけでなく、幅広い処理に対応しているため、ぱっと見何をやっているのかわかりにくくなりがちです。システム開発現場で実装する際も、mapの使用が推奨されている開発現場が多いです。

filterの概念と基本的な使い方

次に、filterの概念と基本的な使い方をサンプルコードを用いつつ説明します。filter関数もmap同様第一引数に条件となる関数を、第二引数に処理対象となるオブジェクトを記述します。

それではさっそくサンプルコードを見てみましょう。

before_list = list(range(10)) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
after_list = filter(even_odd_checker, before_list)
print(list(after_list))

def even_odd_checker (x:int)->bool:
     "#偶数ならTrue, 奇数ならFalseを返す
     return x % 2 ==0

上記のソースコードを実行すると、以下のようにコンソール出力されます。

[0, 2, 4, 6, 8]

下のブロックは、自分で定義した偶数と帰趨を判定するロジックです。偶数ならtrueを返し、奇数ならfalseを返します。filterの第一引数に偶数奇数判定のメソッドを指定した結果、listからtrueに該当する偶数のみが取り出されました。

0が偶数かどうかは微妙ですが、2で割った余りが0になるものと下のブロックで実装しているため、0も該当します。今回メソッドを作成しましたが、map同様lambdaを使用して指定することも可能です。サンプルコードを見てみましょう。

before_list = list(range(10,20)) # [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
after_list = filter(lambda x:x % 2 ==0, before_list)
print(list(after_list))

上記のソースコードを実行すると、以下のようにコンソール出力されます。

[10, 12, 14, 16, 18]

別でメソッドを定義する必要がなくなったため、一行で済むようなロジックであればlambda内で定義した方が効率的でしょう。次に、リスト内包表記で記述してみます。

before_list = list(range(10,20)) # [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
after_list = [x for x in before_list if x % 2 == 0]
print(after_list)

上記のソースコードを実行してコンソール出力すると、以下のようになります。

[10, 12, 14, 16, 18]

まったく同じ結果になりました。このように、filterと同じことがlistの機能で実装できました。同じコードを別の書き方でも実現できることは多いのですが、具体的にどのコードを使用するかは現場規約等によります。

たとえばlistの機能ではfilter同様mapと同じことを実装することも可能であるため、ぱっと見何をやっているのかわからないことがあります。コメントがあったり詳細にトレースすれば処理内容はわかるのですが、基本的にプログラムは読みやすければ読みやすいほど良いです。

filterやmapを使って実装すれば一瞬で処理の目的はわかるので、システム開発現場でも好まれるコードになります。ちなみに、Pythonの高階関数でよく使われるものにはもう一つreduceがあります。

mapやfilterほどではありませんが、要素の演算処理が必要なシステムではreduceの使用頻度も多いです。reduceを直訳すると減らすですが、reduceは引き算だけでなく足し算、掛け算、割り算などにも対応しています。

書き方もmapやfilterと同じで、たとえば以下のようになります。

reduce(add, before_list)
reduce (lambda x, y: x + y, before_list)

list内の要素を足していく処理です。細かい書き方を覚えておく必要はありませんが、だいたい上記のような処理を実装できる、と把握しておくと良いですね。

Python関連記事
1,【Pythonのフリーランス求人・案件情報】エンジニア開発単価は?未経験でもいける?
2,Pythonでできることとは?人工知能で強みを発揮!
3,Pythonのインストール方法をまとめてみた
4,Pythonプログラミングに便利なAnacondaとは?機能やPycharmとの違いを解説
5,PythonでAnacondaをインストールする方法から実際の使い方までを解説
6,Pythonの配列を徹底解説!宣言や追加・削除など
7,Pythonのif文の使い方を解説!演算子もおさらい
8,Pythonのfor文の使い方を配列で解説!breakやrangeの使い方もこれでOK
9,Pythonのlambda(ラムダ式)の使い方を徹底解説します
10,Pythonの高階関数map/filterの便利な使い方(この記事)
11,Pythonでclassをどう使う?技術顧問に聞いてみた!

キャリアカウンセリングのプロとして
あなたに合った案件をご案内します。

まずはお気軽にお問い合わせください!

イメージ