Python でイテレータをチャンク (n 個) ごとに反復処理しますか? 質問する

Python でイテレータをチャンク (n 個) ごとに反復処理しますか? 質問する

イテレータを指定されたサイズのチャンクに分割する良い方法(おそらく itertools を使用)を思いつきますか?

したがって、l=[1,2,3,4,5,6,7]chunks(l,3)イテレータになる[1,2,3], [4,5,6], [7]

それを実行するための小さなプログラムは思いつきますが、おそらく itertools を使った良い方法ではないでしょう。

ベストアンサー1

ドキュメントgrouper()のレシピitertoolsレシピあなたが望むものに近づきます:

def grouper(iterable, n, *, incomplete='fill', fillvalue=None):
    "Collect data into non-overlapping fixed-length chunks or blocks"
    # grouper('ABCDEFG', 3, fillvalue='x') --> ABC DEF Gxx
    # grouper('ABCDEFG', 3, incomplete='strict') --> ABC DEF ValueError
    # grouper('ABCDEFG', 3, incomplete='ignore') --> ABC DEF
    args = [iter(iterable)] * n
    if incomplete == 'fill':
        return zip_longest(*args, fillvalue=fillvalue)
    if incomplete == 'strict':
        return zip(*args, strict=True)
    if incomplete == 'ignore':
        return zip(*args)
    else:
        raise ValueError('Expected fill, strict, or ignore')

ただし、最後のチャンクが不完全な場合は、モードに応じて、incomplete最後のチャンクをフィル値で埋めるか、例外を発生させるか、または不完全なチャンクを暗黙的に削除するため、これはうまく機能しません。

最近のレシピではbatchedその通りあなたが欲しいもの:

def batched(iterable, n):
    "Batch data into tuples of length n. The last batch may be shorter."
    # batched('ABCDEFG', 3) --> ABC DEF G
    if n < 1:
        raise ValueError('n must be at least one')
    it = iter(iterable)
    while (batch := tuple(islice(it, n))):
        yield batch

最後に、シーケンスに対してのみ機能し、最後のチャンクを必要に応じて処理し、元のシーケンスの型を保持する、あまり一般的ではないソリューションは次のとおりです。

(my_list[i:i + chunk_size] for i in range(0, len(my_list), chunk_size))

Python 3.12以降では、 を使用することもできますitertools.batchedドキュメント:

itertools.batched(反復可能オブジェクト、n)

反復可能オブジェクトからのデータを長さ n のタプルにバッチ処理します。最後のバッチは n より短くなる場合があります。

おすすめ記事