2021-04-11に投稿

Python 標準ライブラリ itertools イテレータツール

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))
# =&gt; [('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')]
Originally published at marusankakusikaku.jp
ツイッターでシェア
みんなに共有、忘れないようにメモ

maru3kaku4kaku

Pythonこつこつ学習中。よく忘れる。

Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。

また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!

有料記事を販売できるようになりました!

こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?

コメント