Python Language
Itertoolsモジュール
サーチ…
構文
import itertools
関数を使用して反復可能オブジェクトから項目をグループ化する
グループ化する必要がある繰り返し可能なものから開始する
lst = [("a", 5, 6), ("b", 2, 4), ("a", 2, 5), ("c", 2, 6)]
グループ化されたジェネレータを生成し、各タプルの2番目の要素でグループ化します。
def testGroupBy(lst):
groups = itertools.groupby(lst, key=lambda x: x[1])
for key, group in groups:
print(key, list(group))
testGroupBy(lst)
# 5 [('a', 5, 6)]
# 2 [('b', 2, 4), ('a', 2, 5), ('c', 2, 6)]
連続する要素のグループのみがグループ化されます。 groupby for Egを呼び出す前に同じキーでソートする必要があるかもしれません(最後の要素が変更されます)
lst = [("a", 5, 6), ("b", 2, 4), ("a", 2, 5), ("c", 5, 6)]
testGroupBy(lst)
# 5 [('a', 5, 6)]
# 2 [('b', 2, 4), ('a', 2, 5)]
# 5 [('c', 5, 6)]
groupbyによって返されたグループは、次の繰り返しの前に無効になるイテレータです。たとえば、グループをキーでソートする場合は、次のようには機能しません。グループ2がフェッチされると、グループ5は無効になります
lst = [("a", 5, 6), ("b", 2, 4), ("a", 2, 5), ("c", 2, 6)]
groups = itertools.groupby(lst, key=lambda x: x[1])
for key, group in sorted(groups):
print(key, list(group))
# 2 [('c', 2, 6)]
# 5 []
ソートを正しく行うには、ソート前にイテレータからリストを作成します
groups = itertools.groupby(lst, key=lambda x: x[1])
for key, group in sorted((key, list(group)) for key, group in groups):
print(key, list(group))
# 2 [('b', 2, 4), ('a', 2, 5), ('c', 2, 6)]
# 5 [('a', 5, 6)]
発電機のスライスを取る
Itertools "islice"では、ジェネレーターをスライスすることができます:
results = fetch_paged_results() # returns a generator
limit = 20 # Only want the first 20 results
for data in itertools.islice(results, limit):
print(data)
通常、ジェネレータをスライスすることはできません:
def gen():
n = 0
while n < 20:
n += 1
yield n
for part in gen()[:3]:
print(part)
あげる
Traceback (most recent call last):
File "gen.py", line 6, in <module>
for part in gen()[:3]:
TypeError: 'generator' object is not subscriptable
しかし、これは動作します:
import itertools
def gen():
n = 0
while n < 20:
n += 1
yield n
for part in itertools.islice(gen(), 3):
print(part)
通常のスライスと同様に、 start
、 stop
、 step
引数も使用できます。
itertools.islice(iterable, 1, 30, 3)
itertools.product
この関数は、繰り返し可能なリストのデカルト積を反復することを可能にします。
例えば、
for x, y in itertools.product(xrange(10), xrange(10)):
print x, y
は
for x in xrange(10):
for y in xrange(10):
print x, y
可変数の引数を受け付けるすべてのPython関数と同様に、*演算子を使用して、展開するためにitertools.productにリストを渡すことができます。
このように、
its = [xrange(10)] * 2
for x,y in itertools.product(*its):
print x, y
前述の両方の例と同じ結果が得られます。
>>> from itertools import product
>>> a=[1,2,3,4]
>>> b=['a','b','c']
>>> product(a,b)
<itertools.product object at 0x0000000002712F78>
>>> for i in product(a,b):
... print i
...
(1, 'a')
(1, 'b')
(1, 'c')
(2, 'a')
(2, 'b')
(2, 'c')
(3, 'a')
(3, 'b')
(3, 'c')
(4, 'a')
(4, 'b')
(4, 'c')
itertools.count
前書き:
この単純な関数は、無限の数列を生成します。例えば...
for number in itertools.count():
if number > 20:
break
print(number)
我々は壊れなければならないこと、あるいは永遠に印刷することに注意してください!
出力:
0
1
2
3
4
5
6
7
8
9
10
引数:
count()
はstart
とstep
2つの引数を取ります:
for number in itertools.count(start=10, step=4):
print(number)
if number > 20:
break
出力:
10
14
18
22
itertools.takewhile
itertools.takewhileを使用すると、シーケンスの項目を最初に条件がFalse
なるまで取得できます。
def is_even(x):
return x % 2 == 0
lst = [0, 2, 4, 12, 18, 13, 14, 22, 23, 44]
result = list(itertools.takewhile(is_even, lst))
print(result)
これは[0, 2, 4, 12, 18]
0、2、4、12、18 [0, 2, 4, 12, 18]
出力します。
述語に違反する最初の数(すなわち、ブール値を返す関数) is_even
は、 13
ことに注意してください。 takewhile
が与えられた述語に対してFalse
を生成する値に出会ったら、それは壊れます。
生成される出力 takewhile
以下のコードから生成された出力に類似しています。
def takewhile(predicate, iterable):
for x in iterable:
if predicate(x):
yield x
else:
break
注: takewhile
とdropwhile
によって生成された結果を連結すると、元のiterableが生成されます。
result = list(itertools.takewhile(is_even, lst)) + list(itertools.dropwhile(is_even, lst))
itertools.dropwhile
itertools.dropwhileを使用すると、条件が最初にFalse
後にシーケンスからアイテムを取得できます。
def is_even(x):
return x % 2 == 0
lst = [0, 2, 4, 12, 18, 13, 14, 22, 23, 44]
result = list(itertools.dropwhile(is_even, lst))
print(result)
これは[13, 14, 22, 23, 44]
13,14,22,23,44 [13, 14, 22, 23, 44]
出力します。
( この例は、 takewhile
例と同じtakewhile
が、 dropwhile
を使用してdropwhile
ます ) 。
述語に違反する最初の数(すなわち、ブール値を返す関数) is_even
は、 13
ことに注意してください。その前のすべての要素は破棄されます。
生成される出力 dropwhile
以下のコードから生成された出力に類似しています。
def dropwhile(predicate, iterable):
iterable = iter(iterable)
for x in iterable:
if not predicate(x):
yield x
break
for x in iterable:
yield x
takewhile
とdropwhile
によって生成された結果の連結は元のiterableを生成します。
result = list(itertools.takewhile(is_even, lst)) + list(itertools.dropwhile(is_even, lst))
両方のイテレーターが使い果たされるまで2つのイテレーターを圧縮する
組み込み関数zip()
と同様に、 itertools.zip_longest
は2つのitertools.zip_longest
うちの短い方の端を超えて反復を続けます。
from itertools import zip_longest
a = [i for i in range(5)] # Length is 5
b = ['a', 'b', 'c', 'd', 'e', 'f', 'g'] # Length is 7
for i in zip_longest(a, b):
x, y = i # Note that zip longest returns the values as a tuple
print(x, y)
オプションのfillvalue
引数を渡すことができます(デフォルトは''
)。
for i in zip_longest(a, b, fillvalue='Hogwash!'):
x, y = i # Note that zip longest returns the values as a tuple
print(x, y)
Python 2.6と2.7では、この関数はitertools.izip_longest
と呼ばれていitertools.izip_longest
。
Itertoolsモジュールの組み合わせ方法
itertools.combinations
は、リストのk-コンビネーションシーケンスのジェネレータを返します。
言い換えれば 、入力リストのすべての可能なk-wise組み合わせのタプルのジェネレータを返します。
例えば:
リストがある場合:
a = [1,2,3,4,5]
b = list(itertools.combinations(a, 2))
print b
出力:
[(1, 2), (1, 3), (1, 4), (1, 5), (2, 3), (2, 4), (2, 5), (3, 4), (3, 5), (4, 5)]
上記の出力は、入力リストa
のすべての可能な対の組み合わせのタプルのリストに変換された生成器でa
3つのすべての組み合わせを見つけることもできます:
a = [1,2,3,4,5]
b = list(itertools.combinations(a, 3))
print b
出力:
[(1, 2, 3), (1, 2, 4), (1, 2, 5), (1, 3, 4),
(1, 3, 5), (1, 4, 5), (2, 3, 4), (2, 3, 5),
(2, 4, 5), (3, 4, 5)]
複数のイテレータを連鎖させる
itertools.chain
を使用して、複数のジェネレータの値をitertools.chain
に出力する単一のジェネレータを作成します。
from itertools import chain
a = (x for x in ['1', '2', '3', '4'])
b = (x for x in ['x', 'y', 'z'])
' '.join(chain(a, b))
結果:
'1 2 3 4 x y z'
別のコンストラクタとして、クラスメソッドchain.from_iterable
を使用できます。このメソッドは、単一のパラメータとしてiterableの繰り返し可能なものをとります。上記と同じ結果を得るには:
' '.join(chain.from_iterable([a,b])
chain
は任意の数の引数を取ることができますが、 chain.from_iterable
は無制限のiterableを連結する唯一の方法です。
itertools.repeat
n回繰り返す:
>>> import itertools
>>> for i in itertools.repeat('over-and-over', 3):
... print(i)
over-and-over
over-and-over
over-and-over
繰り返し可能な数値の累積合計を得る
accumulate
と、数の累積合計(または積) accumulate
得られます。
>>> import itertools as it
>>> import operator
>>> list(it.accumulate([1,2,3,4,5]))
[1, 3, 6, 10, 15]
>>> list(it.accumulate([1,2,3,4,5], func=operator.mul))
[1, 2, 6, 24, 120]
イテレータの要素を循環させる
cycle
は無限の反復子です。
>>> import itertools as it
>>> it.cycle('ABCD')
A B C D A B C D A B C D ...
したがって、無限ループを避けるためにこれを使用する場合は、境界を与えるように注意してください。例:
>>> # Iterate over each element in cycle for a fixed range
>>> cycle_iterator = it.cycle('abc123')
>>> [next(cycle_iterator) for i in range(0, 10)]
['a', 'b', 'c', '1', '2', '3', 'a', 'b', 'c', '1']
itertools.permutations
itertools.permutations
は、反復可能な要素の連続したr長の置換を持つジェネレータを返します。
a = [1,2,3]
list(itertools.permutations(a))
# [(1, 2, 3), (1, 3, 2), (2, 1, 3), (2, 3, 1), (3, 1, 2), (3, 2, 1)]
list(itertools.permutations(a, 2))
[(1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)]
リストの場合はa
重複要素を持って、その結果の順列は、あなたが使用することができ、重複した要素を持っていますset
ユニークな順列を取得します:
a = [1,2,1]
list(itertools.permutations(a))
# [(1, 2, 1), (1, 1, 2), (2, 1, 1), (2, 1, 1), (1, 1, 2), (1, 2, 1)]
set(itertools.permutations(a))
# {(1, 1, 2), (1, 2, 1), (2, 1, 1)}