Pythonの組み込み関数であるfilter関数を使ってリストから条件を満たす要素を抽出する方法を解説します。
Contents
filter関数でリストから条件を満たす要素を抽出する
filter関数は、関数と処理対象のイテラブルを受け取って、特定の条件を満たす要素を抽出するPythonの組み込み関数です。
このように引数に関数を受け取る関数は高階関数と言います。for文で処理しても同じ処理ができますが、繰り返し処理を書かずともシンプルに記載できる点がメリットです。
filter関数は、関数型プログラミング言語において中心的な関数です。Pythonはマルチパラダイムの言語と言われているため、厳密ではありませんが関数型のプログラミングスタイルもサポートしており、filter関数が組み込み関数として利用できるようになっています。
本記事では、リストの要素へ関数を適用してフィルタする例を用いて、filter関数の使い方の基本を紹介します。
filter関数と同じく関数型プログラミングに関連のある関数としてmap関数、reduce関数、partial関数があります。以下のページでまとめていますので興味があれば参考にしてください。
filter関数の基本的な使い方
filter関数の基本的な構文は以下のようになります。
result = filter(関数, イテラブル)
filter関数では、イテラブルの各要素に関数を適用し条件を満たす要素を抽出した結果のイテレータを返却します。イテレータは値を逐次取り出せるオブジェクトでnext
を用いることで順に関数を適用した値を取り出したり、for文で使用することができます。後述の例でも見ますが、list(filter(関数, イテラブル))
のようにすることでリストに変換して取得することも可能です。
また、filter関数は条件を満たす要素を抽出することが目的であるため、指定する関数は、与えられた要素に対してTrue
またはFalse
を返却する関数である必要があります。
なお、イテレータについては「イテレータ(iterator)の基本」でまとめていますので興味があれば参考にしてください。
以降で、filter関数のいくつかの使い方について例を使ってみていきましょう。
基本的な使い方
filter関数の基本的な使い方を以下の例を用いて見ていきましょう。
def is_even(num): """数値が偶数か判定する""" return num % 2 == 0 if __name__ == "__main__": tmp_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # filter関数を適用し、イテレータを取得 result = filter(is_even, tmp_list) print(result, "\n") # nextで1要素ずつ結果データを取得 print(next(result)) print(next(result)) print(next(result)) print(next(result)) print(next(result))
【実行結果】 <filter object at 0x000001FA10FB45E0> 2 4 6 8 10
上記の例では、受け取った数値が偶数かどうかを判定するis_even
関数が定義されており、tmp_list
の各要素が偶数かどうかをフィルタしています。
filter関数を呼び出している部分では「filter(is_even, tmp_list)
」というように関数と処理対象のリストを渡しています。ここでポイントは、関数を渡す際に()
がないことです。関数はis_even(2)
のように()
で引数を指定すると関数を実行することを意味しますが、()
がない場合は関数そのものを表します。filter関数は、受け取ったis_even
という関数を内部で実行しているわけです。
また、filter関数は条件を満たす要素を抽出することが目的であるため、指定する関数は、is_even
関数のように与えられた要素に対してTrue
またはFalse
を返却する関数である必要があります。
filter関数の返却値は「filter object」となっていますが、これはイテレータの一種です。next
関数を使用することで次の要素を順番に取得することができます。この例では、tmp_list
の要素で偶数である数値が順に取得されていることが分かります。
上記例でnext(result)
を追加して再度実行するとStopIteration
例外が発生します。これはイテレータがもう要素を持たない場合に発生する例外です。StopIteration
は、forループ等の繰り返しの終了を示すために使用されます。
【実行結果】 Traceback (most recent call last): ...(省略)... StopIteration
リストやタプルで取得する場合
filter関数の返却値はイテレータですが、以下のようにlist
やtuple
に渡すことによってリストやタプルとして結果を取得することができます。
def is_even(num): """数値が偶数か判定する""" return num % 2 == 0 if __name__ == "__main__": tmp_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # filter関数を適用し、リストで取得 result = list(filter(is_even, tmp_list)) print(result) # filter関数を適用し、タプルで取得 result = tuple(filter(is_even, tmp_list)) print(result)
【実行結果】 [2, 4, 6, 8, 10] (2, 4, 6, 8, 10)
上記結果を見るとリストやタプルとして結果を受け取れていることが分かるかと思います。
ラムダ関数(無名関数)と組み合わせる場合
filter関数は、ラムダ関数(無名関数)と組み合わせることで、一時的な小さな関数を定義せずに使用することができます。
ラムダ関数は関数型プログラミングでもとても重要な概念です。ラムダ関数については「ラムダ(lambda)関数:無名関数の使い方」でまとめていますので興味があれば参考にしてください。
上記で見てきたis_even
関数をラムダ関数にしてfilter関数で使う例を以下で見てみましょう。
tmp_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # filter関数を適用し、リストで取得 result = list(filter(lambda x: x % 2 == 0, tmp_list)) print(result) # filter関数を適用し、タプルで取得 result = tuple(filter(lambda x: x % 2 == 0, tmp_list)) print(result)
【実行結果】 [2, 4, 6, 8, 10] (2, 4, 6, 8, 10)
これまでの例でis_even
と関数を指定していた部分で「lambda x: x % 2 == 0
」というようなラムダ関数を指定しています。結果はis_even
関数を使った場合と一緒になっていることが分かります。
ラムダ関数は無名関数ともいわれる通り、関数名はありませんが式そのものが関数扱いになります。そのため、filter関数にラムダ関数を渡すことでリストの各要素に関数を適用できます。
まとめ
Pythonの組み込み関数であるfilter関数を使ってリストから条件を満たす要素を抽出する方法を解説しました。
filter関数は、関数と処理対象のイテラブルを受け取って、特定の条件を満たす要素を抽出するPythonの組み込み関数です。filter関数は他の関数型プログラミング言語でも中心的な関数でPythonでも使用できます。
filter関数はfor文を用いなくてもシンプルに関数を適用したフィルタができることが特徴です。非常に強力な機能ですが、filter関数の適用が常に最適な選択というわけではありません。場合によってはfor文で書いた方が可読性が上がる可能性もあります。
目的に応じて適切に方法を選択できるように、filter関数の使い方を理解し、覚えておいてもらうとよいかと思います。
上記で紹介しているソースコードについてはgithubにて公開しています。参考にしていただければと思います。