「おそらく知らなかった4つのPython Itertoolsフィルター関数」
4 Python Itertools Filter Functions You Probably Didn't Know
Pythonでは、イテレータを使用することで、よりPythonicなコードを書くことができ、長いシーケンスをより効率的に処理することができます。組み込みのitertoolsモジュールは、いくつかの便利な関数を提供して、イテレータを作成します。
これらは、イテレータを単にループしてシーケンス内の要素を取得し、それらを処理する場合に特に役立ちます。すべての要素をメモリに格納することなく、これらの関数を使用する方法を学びましょう。今日は以下の4つのitertoolsフィルタ関数の使用方法を学びます:
- filterfalse
- takewhile
- dropwhile
- islice
では、始めましょう!
始める前に: コード例に関する注意事項
このチュートリアルでは:
- 4つの関数はすべてイテレータを返します。わかりやすさのため、単純なシーケンスで作業し、
list()
を使用してイテレータが返すすべての要素を含むリストを取得します。ただし、長いシーケンスで作業する場合は、必要な場合以外はこれを行わないでください。なぜなら、そうするとイテレータのメモリの節約効果が失われるからです。 - 単純な述語関数の場合、ラムダを使用することもできます。ただし、可読性のために、通常の関数を定義して述語として使用します。
1. filterfalse
Pythonで長い間プログラミングをしている場合、おそらく組み込みのfilter
関数を次のような構文で使用したことがあるでしょう:
filter(pred,seq)
# pred: 述語関数
# seq: 有効なPythonのイテラブル
filter
関数は、述語がTrue
を返すシーケンスの要素を返すイテレータを返します。
例を見てみましょう:
nums = list(range(1,11)) #[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
def is_even(n):
return n % 2 == 0
ここで、nums
リストとis_even
関数は、シーケンスと述語です。
nums
のすべての偶数のリストを取得するには、次のようにfilter
を使用します:
nums_even = filter(is_even, nums)
print(list(nums_even))
出力 >>> [2, 4, 6, 8, 10]
次に、filterfalse
について学びましょう。 filterfalse
関数(および他のすべての関数)をitertoolsモジュールからインポートします。
名前からわかるように、filterfalse
はfilter
関数の逆の動作をします。述語がFalse
を返す要素を返すイテレータを返します。 filterfalse
関数の構文は次のとおりです:
from itertools import filterfalse
filterfalse(pred,seq)
is_even
関数はnums
のすべての奇数に対してFalse
を返します。したがって、filterfalse
を使用して取得されるnums_odd
リストは、nums
のすべての奇数のリストです:
from itertools import filterfalse
nums_odd = filterfalse(is_even, nums)
print(list(nums_odd))
出力 >>> [1, 3, 5, 7, 9]
2. takewhile
takewhile
関数を使用するための構文は次のとおりです:
from itertools import takewhile
takewhile(pred,seq)
takewhile
関数は、述語関数がTrue
を返す限り要素を返すイテレータを生成します。述語がFalse
を返した場合、要素の返却を停止します。
n要素のシーケンスに対して、述語関数がFalse
を返す最初の要素がseq[k]
である場合、イテレータはseq[0]
, seq[1]
,…, seq[k-1]
を返します。
以下のnums
リストと述語関数is_less_than_5
を考えてみましょう。以下のようにtakewhile
関数を使用します:
from itertools import takewhile
def is_less_than_5(n):
return n < 5
nums = [1, 3, 5, 2, 4, 6]
filtered_nums_1 = takewhile(is_less_than_5, nums)
print(list(filtered_nums_1))
ここでは、述語is_less_than_5
は数値5に対して最初のFalse
を返します:
出力 >>> [1, 3]
3. dropwhile
機能的には、dropwhile
関数はtakewhile
関数の逆を行います。
以下のようにdropwhile
関数を使用することができます:
from itertools import dropwhile
dropwhile(pred,seq)
dropwhile
関数は、述語がTrue
である限り要素を除外し続けるイテレータを生成します。述語が最初のFalse
を返すまでは何も返しません。そして、述語がFalse
を返した後は、シーケンス内のその後の要素をすべて返します。
n要素のシーケンスに対して、述語関数がFalse
を返す最初の要素がseq[k]
である場合、イテレータはseq[k]
, seq[k+1]
,…, seq[n-1]
を返します。
同じシーケンスと述語を使用してみましょう:
from itertools import dropwhile
def is_less_than_5(n):
return n < 5
nums = [1, 3, 5, 2, 4, 6]
filtered_nums_2 = dropwhile(is_less_than_5, nums)
print(list(filtered_nums_2))
述語関数is_less_than_5
は最初のFalse
として要素5を返すため、シーケンスの要素5から始まるすべての要素が返されます:
出力 >>> [5, 2, 4, 6]
4. islice
すでにリスト、タプル、文字列などのPythonの反復可能なオブジェクトのスライシングについてはおなじみでしょう。スライシングの構文はiterable[start:stop:step]
です。
ただし、このスライシングの方法には以下のような欠点があります:
- 大きなシーケンスで作業する場合、各スライスまたは部分シーケンスはメモリを占有するコピーです。これは非効率的です。
- ステップには負の値も使用できるため、開始、停止、およびステップの値を使用すると可読性に影響します。
islice
関数は上記の制約に対処します:
- イテレータを返します。
- ステップには負の値を使用することはできません。
以下のようにislice
関数を使用することができます:
from itertools import islice
islice(seq,start,stop,step)
以下は、islice
関数を使用するいくつかの異なる方法です:
islice(seq, stop)
を使用すると、seq[0]
、seq[1]
、…、seq[stop - 1]
のスライス上で反復するイテレータが返されます。- 開始値と終了値を指定する場合:
islice(seq, start, stop)
は、seq[start]
、seq[start + 1]
、…、seq[start + stop - 1]
のスライス上で反復するイテレータが返されます。 - 開始値、終了値、ステップ引数を指定する場合、関数は
seq[start]
、seq[start + step]
、seq[start + 2*step]
、…、seq[start + k*step]
のスライス上で反復するイテレータを返します。ただし、start + k*step
<stop
かつstart + (k+1)*step
>=stop
となるようにします。
これをよりよく理解するために、例としてリストを使用しましょう:
nums = list(range(10)) #[0,1, 2, 3, 4, 5, 6, 7, 8, 9]
では、学んだ構文を使用してislice
関数を使ってみましょう。
ストップ値のみを使用する
ストップインデックスのみを指定しましょう:
from itertools import islice
# only stop
sliced_nums = islice(nums, 5)
print(list(sliced_nums))
以下は出力です:
出力 >>> [0, 1, 2, 3, 4]
開始値と終了値を使用する
ここでは、開始値と終了値の両方を使用します:
# start and stop
sliced_nums = islice(nums, 2, 7)
print(list(sliced_nums))
スライスはインデックス2から7までの範囲で、7を含まないようになっています:
出力 >>> [2, 3, 4, 5, 6]
開始値、終了値、ステップ値を使用する
開始値、終了値、ステップ値を使用する場合:
# using start, stop, and step
sliced_nums = islice(nums, 2, 8, 2)
print(list(sliced_nums))
インデックス2から8までの範囲で、ステップサイズが2(2つおきに返す)のスライスが得られます。
出力 >>> [2, 4, 6]
まとめ
このチュートリアルがitertoolsのフィルタ関数の基本を理解するのに役立ったことを願っています。これらの関数の動作をよりよく理解するためのいくつかの簡単な例を見ました。次に、効率的なPythonイテレータとしてのジェネレータ関数とジェネレータ式の動作について学ぶことができます。 Bala Priya Cは、インド出身の開発者兼技術ライターです。彼女は数学、プログラミング、データサイエンス、コンテンツ作成の交差点での作業が好きです。彼女の関心と専門知識の範囲には、DevOps、データサイエンス、自然言語処理が含まれます。彼女は読書、執筆、コーディング、コーヒーが好きです!現在、彼女はチュートリアル、ハウツーガイド、意見記事などを執筆することで、開発者コミュニティと彼女の知識を共有するための学習に取り組んでいます。
We will continue to update VoAGI; if you have any questions or suggestions, please contact us!
Was this article helpful?
93 out of 132 found this helpful
Related articles