Python 標準ライブラリ itertools イテレータツール
Publish date: 2021-04-11
Python標準ライブラリitertoolsを使うと、イテレータを加工したイテレータの構築を簡単に行うことができます。
itertoolsで提供されている関数
accumulate(iterable[, func, *, initial=None]) 演算を蓄積した結果をイテレータで取得
import itertools
import operator
# func:省略時はoperator.add
# initial:演算を行う際の値の初期値
items = [1, 2, 3, 4]
list(itertools.accumulate(items)) # => [1, 3, 6, 10]
list(itertools.accumulate(items, initial=10)) # => [10, 11, 13, 16, 20]
list(itertools.accumulate(items, lambda x,y: x-y)) # => [1, -1, -4, -8]
list(itertools.accumulate(items,operator.mul)) # => [1, 2, 6, 24]
chain(*iterables) イテレータを順次取得
list(itertools.chain([1,2,3],[4,5])) # => [1, 2, 3, 4, 5]
chain.from_iterable イテレータを順次取得
list(itertools.chain.from_iterable([[1,2,3],[4,5]])) # => [1, 2, 3, 4, 5]
combinations(iterable, r) イテレータの要素から長さrで組み合わせを取得
list(itertools.combinations("abc",2)) # => [('a', 'b'), ('a', 'c'), ('b', 'c')]
combinations_with_replacement(iterable, r) イテレータの要素から長さrで組み合わせを取得(重複あり))
list(itertools.combinations_with_replacement("abc",2))
# => [('a', 'a'), ('a', 'b'), ('a', 'c'), ('b', 'b'), ('b', 'c'), ('c', 'c')]
compress(data, selectors) selectorsがtrueの位置に対応するdataの要素を取得
list(itertools.compress("abcde",[1,0,0,1,0])) # => ['a', 'd']
list(itertools.compress("abcde",[1,0,1])) # => ['a', 'c']
count(start=0, step=1) 等間隔のイテレータ
for i,item in enumerate(itertools.count()):
if(3 < i):
break
print(item) # => 0 1 2 3
for i,item in enumerate(itertools.count(10)):
if(3 < i):
break
print(item) # => 10 11 12 13
for i,item in enumerate(itertools.count(10, 0.1)):
if(3 < i):
break
print(item) # => 10 10.1 10.2 10.299999999999999
cycle(iterable) 繰り返しのイテレータ
for i,item in enumerate(itertools.cycle("abc")):
if(6 < i):
break
print(item) # => a b c a b c
dropwhile(predicate, iterable) 条件が真の間最初だけ要素を飛ばす
list(itertools.dropwhile(lambda x: x%2==0, [2,4,5,7,8,9,10])) # => [5, 7, 8, 9, 10]
filterfalse(predicate, iterable) 条件がFalseの間だけ要素を返す
list(itertools.filterfalse(lambda x: x%2==0, [2,4,5,7,8,9,10])) # => [5, 7, 9]
groupby(iterable, key=None) 連続した値の要素のイテレータとキーを取得
groups = []
uniquekeys = []
for k, g in itertools.groupby("AAAABBBCCDAABBB"):
groups.append(list(g))
uniquekeys.append(k)
print(groups) # => [['A', 'A', 'A', 'A'], ['B', 'B', 'B'], ['C', 'C'], ['D'], ['A', 'A'], ['B', 'B', 'B']]
print(uniquekeys) # => ['A', 'B', 'C', 'D', 'A', 'B']
グループとなるキーの区切りでイテレータが変わるため予めソートして使う。
groups = []
uniquekeys = []
for k, g in itertools.groupby(sorted("AAAABBBCCDAABBB")):
groups.append(list(g))
uniquekeys.append(k)
print(groups) # => [['A', 'A', 'A', 'A', 'A', 'A'], ['B', 'B', 'B', 'B', 'B', 'B'], ['C', 'C'], ['D']]
print(uniquekeys) # => ['A', 'B', 'C', 'D']
キーが要素自身ではない場合keyに取得方法を指定する。
class SampleData:
def __init__(self, key, name):
self.key = key
self.name = name
items = [SampleData(x % 3,chr(65+x)) for x in range(10)]
items = sorted(items,key=lambda x:x.key)
groups = []
uniquekeys = []
for k, g in itertools.groupby(items,key=lambda x:x.key):
groups.append(list(g))
uniquekeys.append(k)
islice(iterable, stop) 要素を選択して取得する
list(itertools.islice("ABCDEFGHIJ", 3)) # => ['A', 'B', 'C']
islice(iterable, start, stop[, step]) 要素を選択して取得する
list(itertools.islice("ABCDEFGHIJ", 3, 7)) # => ['D', 'E', 'F', 'G']
list(itertools.islice("ABCDEFGHIJ", 3, 7, 2)) # => ['D', 'F']
permutations(iterable, r=None) イテレータから順列で繰り返し取得
list(itertools.permutations("abc", 2)) # => [('a', 'b'), ('a', 'c'), ('b', 'a'), ('b', 'c'), ('c', 'a'), ('c', 'b')]
list(itertools.permutations("abc", 3))
# => [('a', 'b', 'c'), ('a', 'c', 'b'),('b', 'a', 'c'), ('b', 'c', 'a'), ('c', 'a', 'b'), ('c', 'b', 'a')]
product(*iterables, repeat=1) イテレータのデカルト積
list(itertools.product("ABC", "xy")) # => [('A', 'x'), ('A', 'y'), ('B', 'x'), ('B', 'y'), ('C', 'x'), ('C', 'y')]
repeat(object[, times]) objectを繰り返すイテレータ
times未指定の場合無限に繰り返す。
list(map(lambda x,y:x+y, range(10), itertools.repeat(5))) # => [5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
list(map(lambda x,y:x+y, range(10), itertools.repeat(5, 3))) # => [5, 6, 7]
starmap(function, iterable) iterableの要素でfunctionを実行するイテレータ
list(itertools.starmap(lambda x,y:x+y, [(1,2), (10,11), (20,21)])) # => [3, 21, 41]
takewhile(predicate, iterable) 上限が真となっている最初の間だけ要素を取得する
list(itertools.takewhile(lambda x:x%2==0, [2,4,5,6,7])) # => [2, 4]
tee(iterable, n=2) n個にイテレータを分割
iters = list(itertools.tee(range(10)))
print(list(iters[0])) # => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(list(iters[1])) # => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
zip_longest(*iterables, fillvalue=None) 一番要素の多いイテレータ分まとめて繰り返し
list(itertools.zip_longest('ABCD', '123')) # => [('A', '1'), ('B', '2'), ('C', '3'), ('D', None)]
list(itertools.zip_longest('ABCD', '123', fillvalue='0')) # => [('A', '1'), ('B', '2'), ('C', '3'), ('D', '0')]
参考
itertools — 効率的なループ実行のためのイテレータ生成関数