関数

【Python】filter関数の使い方の基本 ~条件を満たす要素を抽出~

【Python】filter関数の使い方の基本 ~リストから条件を満たす要素を抽出~
naoki-hn

Pythonの組み込み関数である filter 関数を使ってリストから条件を満たす要素を抽出する方法を解説します。

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 関数の基本的な使い方を以下の例を用いて見ていきましょう。

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 例外が発生します。これはイテレータがもう要素を持たない場合に発生する例外です。StopIterationfor ループ等の繰り返しの終了を判断するために使用されています。

【実行結果】
Traceback (most recent call last):
...(省略)...
StopIteration

リストやタプルで取得する場合

filter 関数の返却値はイテレータであるため、以下のように listtuple に変換することができます。

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 関数では、ラムダ関数(無名関数)と組み合わせることで、より手軽に条件を満たす要素を抽出することができます。ラムダ関数は、関数定義を def で定義することなく、その場で作れるもので関数型プログラミングでは中核の概念です。

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 関数に渡すことでリストの各要素に関数を適用できます。

ラムダ関数の基本については以下を参考にしてください。

ラムダ(lambda)関数:無名関数の使い方

まとめ

Pythonの組み込み関数である filter 関数を使って条件を満たす要素を抽出する方法を解説しました。

filter 関数は、関数と処理対象のイテラブルを受け取って、特定の条件を満たす要素を抽出する Python の組み込み関数です。filter 関数は他の関数型プログラミング言語でも中心的な関数で Python でも使用できます。

filter 関数は for 文を用いなくてもシンプルに関数を適用したフィルタができることが特徴です。非常に強力な機能ではありますが、filter 関数の適用が常に最適な選択というわけではありません。

場合によっては for 文で書いた方が可読性が上がる可能性もあります。目的に応じて適切に方法を選択できるよう filter 関数の使い方を理解しておくようにしましょう。

ソースコード

上記で紹介しているソースコードについては GitHub にて公開しています。参考にしていただければと思います。

あわせて読みたい
【Python Tech】プログラミングガイド
【Python Tech】プログラミングガイド

ABOUT ME
ホッシー
ホッシー
システムエンジニア
はじめまして。当サイトをご覧いただきありがとうございます。 私は製造業のメーカーで、DX推進や業務システムの設計・開発・導入を担当しているシステムエンジニアです。これまでに転職も経験しており、以前は大手電機メーカーでシステム開発に携わっていました。

プログラミング言語はこれまでC、C++、JAVA等を扱ってきましたが、最近では特に機械学習等の分析でも注目されているPythonについてとても興味をもって取り組んでいます。これまでの経験をもとに、Pythonに興味を持つ方のお役に立てるような情報を発信していきたいと思います。どうぞよろしくお願いいたします。

※キャラクターデザイン:ゼイルン様
記事URLをコピーしました