『Python数値計算ノート』ではアフィリエイトプログラムを利用して商品を紹介しています。

filter()

filter()

Python の filter() はリストやタプルなどから、特定の条件を満たす要素を抽出(フィルタリング)する組み込み関数です。filter() 関数の正式構文は

filter(function or None, iterable)

ですが、実用上は filter(関数, リスト) と覚えておけば十分です。ただし、filter に渡す関数は何でもよいというわけでなく、True または False を返すように定義されていなければなりません。簡単な例として、50 以上の数値を渡すと True を返す関数 geq_fifty() と、適当なリストを filter() に渡してみます。

# PYTHON_FILTER

# In[1]

# 受け取った引数が50以上ならTrue,
# それ以外はFalseを返す関数を定義
def geq_fifty(x):
    if x >= 50:
        return True
    else:
        return False

# リストを作成
numbers = [12, 67, 45, 96, 58, 31, 74, 51]

# filter()でnumbersから50以上の数値を抽出する
numbers_geq50 = filter(geq_fifty, numbers)

filter() の戻り値はイテレータとよばれるオブジェクトです。イテレータはリストなどのシーケンスに比べてメモリを節約できますが、必要であれば、list() を使ってイテレータをリストに変換できます。

# In[2]

# イテレータの要素をリストに展開
my_list = list(numbers_geq50)

print(my_list)
# [67, 96, 58, 74, 51]

geq_fifty() を lambda 式 で表すと、次のようなコードになります。

# In[3]

# filter()でリストの中から50以上の数字を抜き出してイテレータを生成
numbers_geq50 = filter(lambda x : x>=50, numbers)

# イテレータの要素をリストに展開
my_list = list(numbers_geq50)

print(my_list)
# [67, 96, 58, 74, 51]

戻り値が常にリストになるような関数を定義しておくのも一つの手です。

# In[4]

# イテラブルから条件に合う要素を抽出し、
# リストに変換する関数を定義
def filter_list(func, iterable):
    new_iterable = filter(func, iterable)
    return list(new_iterable)

# numbersから50以上の数値を抽出する
my_list = filter_list(lambda x : x>=50, numbers)

print(my_list)
# [67, 96, 58, 74, 51]

今度は filter() を使って特定の文字を含む要素を取り出してみましょう。

# In[5]

# 関数型言語のリスト
functional_languages = ["SML", "Haslkell", "Erlang", "Scheme", "Scala"]

# functional_languagesから"S"を含む要素を抽出
f = filter_list(lambda x : x.find("S") != -1, functional_languages)

print(f)
# ["SML", "Scheme", "Scala"]

str.find() は指定した文字列の場所を返すメソッドですが、見つからない場合は -1 を返してきます。x.find(“S”) != -1 は「”S” が -1 ではない」、すなわち「”S” が文字列のどこかに含まれる」を意味しています。
 
filter() の第 1 引数に None を渡すと、第 2 引数のリストをそのままイテレータに変換します。

# In[6]

# filter()の第1引数にNoneを渡すと、イテラブルをイテレータに変換する
numbers_2 = filter(None, numbers)

print(list(numbers_2))
# [12, 67, 45, 96, 58, 31, 74, 51]

 これは以下のように、第 1 引数に恒等関数 (lambda x:x) を指定した場合と同じです。

# In[7]

# 第1引数に恒等関数を渡す
numbers_2 = filter(lambda x : x, numbers)

print(list(numbers_2))
# [12, 67, 45, 96, 58, 31, 74, 51]

Longman Dictionary of Contemporary English (6E) Paperback

新品価格
¥5,560から
(2022/7/12 23:18時点)

itertools.filterfalse()

標準ライブラリの itertools モジュールには itertools.filterfalse() という関数が用意されています。

filterfalse(function or None, sequence)

この関数は、function に sequence の各要素を渡したときに False となる要素だけを抽出してイテレータを構築します。つまり、filter() と真逆の結果を返します。以下のサンプルコードでは「偶数を渡すと True, 奇数を渡すと False を返す関数」を function に渡して、リストから奇数を抜き出したイテレータを生成します。

# Python_itertools_filterfalse

import itertools

# arr=[1,2,3,4,5,6,7,8,9]
arr = range(1, 10)

# iterableから奇数となる要素を抽出する
my_iter = itertools.filterfalse(lambda x : x%2==0, arr)

my_list = list(my_iter)

print(my_list)
# [1, 3, 5, 7, 9]

コメント

  1. BlogCat より:

    【AI連載小説】科学とコードの交差点(49)「filter関数の色々な使い道」
     
    開誠:「filter関数はリストやイテレータから条件に合致する要素を抽出するのに便利だよな。でも、実はこれ、様々なところで使えるんだ」
    美純:「例えばどのような場面で使えるのでしょうか?」
    開誠:「まず、リスト内包表記を使わなくても、filterを使ってコードを簡潔に保つことができる」
    明信:「それとは具体的にどのようなケースが考えられるの?」
    開誠:「たとえば、数値のリストから奇数だけを抽出する場合、filterを使えば以下のように書けるんだ」

    numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
    filtered_numbers = list(filter(lambda x: x % 2 != 0, numbers))
    

    美純:「確かに、これならリスト内包表記よりもシンプルだね」
    開誠:「そうだ。他にもNoneを取り除く、文字列の空白を取り除くなど、様々なシーンで使えるんだ」

    ディスカッションはfilter関数の応用例や使いどころ、ラムダ関数の上手な活用にまで及び、三人はコードの効率性や可読性向上について熟考しながら新しいアイディアを共有していきました。

    明信:「filterは条件に合致する要素を抽出するだけでなく、逆に条件に合わないものを抽出する場合も考えられるね」
    美純:「そのアプローチも面白いわね。データの整理やクリーニングにも使えそう」

  2. あとりえこばと より:

    filter を英英辞典で調べてみると、「特別な物質や装置の一部に液体やガスを通してきれいにする」というような説明が英語で書かれています。つまり「ろ過する・濾す」という意味です。名詞は「ろ過装置」。今は日本語でも普通にフィルターという言葉を使っていますね (コーヒーフィルターなど)。Python の filter() も、条件に合う要素だけを残して、いらない要素は捨ててしまう、いうなれば「ろ過関数」なのです。ちなみに、私が英英辞典を使う理由は、いわゆるネイティブ向けに書かれた「国語辞典」のほうが、英和辞典に比べて意味が正確でニュアンスのずれなどがないからです。英単語を平易な英語で説明しているので、英文を読む訓練にもなって一石二鳥です。英英辞典、おすすめです。