Python学習チャンネル by PyQ

Pythonのオンライン学習プラットフォームPyQのオフィシャルブログです

【Python 3.12の新機能】itertools.batchedの使い方と代替関数

Python 3.12では、標準ライブラリのitertoolsbatchedという関数が追加されました。
batchedは、イテラブルをN個ずつまとめる関数です。
以下は、batchedのヘルプからの抜粋です。7文字を3文字ずつにまとめるサンプルになります。

>>> for batch in batched('ABCDEFG', 3):
...     print(batch)
...
('A', 'B', 'C')
('D', 'E', 'F')
('G',)

早速、次のような課題で使ってみましょう。

課題

A社では、明日の内定式で、内定者10人のグループワークを行います。
グループワークはテーブルごとにします。このテーブルは4人がけなので3グループにわかれます。
グループがランダムになるように割り振ってください。

Pythonで解いてみよう

最初に、10人の内定者のリストを用意しましょう。

names = ['田中', '小林', '佐藤', '松田', '川村', '岡本', '高橋', '坂井', '山田', '井上']

このリストからランダムに4人選ぶことを繰り返すとよさそうです。
最初に、ランダムに並び替えましょう。ランダムに並び替えをするには、randomモジュールのshuffleが使えます。

import random

random.shuffle(names)
print(names)

出力

['小林', '岡本', '松田', '高橋', '川村', '井上', '田中', '山田', '佐藤', '坂井']

namesの並びがランダムになりました。
続いて、グループごとに出力しましょう。先頭から4人ずつ取得するには、下記のようにスライスを使います。

print(names[0:4])  # グループ1
print(names[4:8])  # グループ2
print(names[8:10])  # グループ3

出力

['小林', '岡本', '松田', '高橋']
['川村', '井上', '田中', '山田']
['佐藤', '坂井']

これで、グループごとに出力できました。しかし、このような書き方は、グループが増えると大変です。forを使って書き直してみましょう。

for i in range(0, 10, 4):
    print(names[i:i+4])

出力

['小林', '岡本', '松田', '高橋']
['川村', '井上', '田中', '山田']
['佐藤', '坂井']

書き換えた結果も同じ出力になりました。

最後のグループは、names[8:12]になっていますが、はみ出てた分は無視されるので問題ありません。
これでできたのですが、コードがちょっとわかりにくいです。時間が経つと何をやっているかわからなくなりそうです。

実は、Python 3.12で追加されたitertoolsbatchedを使うと、もっとわかりやすくなります。
やってみましょう。

from itertools import batched

for group in batched(names, 4):
    print(group)

出力

('小林', '岡本', '松田', '高橋')
('川村', '井上', '田中', '山田')
('佐藤', '坂井')

リストがタプルになっていますが、中身は同じになっています。
batchedは、指定の数だけ集めてグループを作る関数です。第2引数が指定の数です。
batched(names, 4)は「namesから4つずつ集めている」ということがわかりやすくなっています。
itertoolsは標準ライブラリなので、準備も不要で使いやすいです。

batchedと同じことは、サードパーティ製ライブラリのmore-itertoolschunkedを使ってもできます。
書き方は、ほぼ同じですね。

from more_itertools import chunked

for group in chunked(names, 4):
    print(group)

出力

['小林', '岡本', '松田', '高橋']
['川村', '井上', '田中', '山田']
['佐藤', '坂井']

この場合は、次のようにmore-itertoolsをインストールすれば、Python 3.11以前でも使えます。

pip install more-itertools

chunkedに似た関数に、chunked_evenというものがあります。
こちらは、グループ内の数の差を最小にするものです。使い方はchunkedと同じです。

from more_itertools import chunked_even

for group in chunked_even(names, 4):
    print(group)

出力

['小林', '岡本', '松田', '高橋']
['川村', '井上', '田中']
['山田', '佐藤', '坂井']

グループの最小人数が2人から3人になりました。グループワークをするには、こちらの方がよさそうですね。

itertools.batchedmore-itertools.chunkedなどについて詳しく知りたい方は、下記も参照してみてください。

docs.python.org

more-itertools.readthedocs.io

Copyright ©2017- BeProud Inc. All rights reserved.