filter()

filter()

filter()

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

filter(function or None, iterable)

ですが、実用上は 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]