1. ホーム
  2. python

[解決済み] イテラブルを一定サイズのチャンクに分割する方法

2022-05-15 01:09:29

質問

重複している可能性があります。

どのようにPythonで均等なサイズのチャンクにリストを分割するには?

私は、反復可能なものを入力として受け取り、反復可能なものの反復可能なものを返す、"batch"関数が見つからなかったことに驚いています。

例えば

for i in batch(range(0,10), 1): print i
[0]
[1]
...
[9]

または

for i in batch(range(0,10), 3): print i
[0,1,2]
[3,4,5]
[6,7,8]
[9]

さて、かなり単純なジェネレータと思われるものを書いてみました。

def batch(iterable, n = 1):
   current_batch = []
   for item in iterable:
       current_batch.append(item)
       if len(current_batch) == n:
           yield current_batch
           current_batch = []
   if current_batch:
       yield current_batch

しかし、上記では私が期待したようなものは得られません。

for x in   batch(range(0,10),3): print x
[0]
[0, 1]
[0, 1, 2]
[3]
[3, 4]
[3, 4, 5]
[6]
[6, 7]
[6, 7, 8]
[9]

私は何かを見逃しており、これはおそらく私のpythonジェネレータの完全な理解不足を示しています。誰か正しい方向に私を指摘する気になりますか?

[編集:私は最終的に、上記の動作は、私がpython自体ではなく、ipython内でこれを実行したときにのみ起こることに気づきました]。

どのように解決するのですか?

この方が効率的(速い)でしょう

def batch(iterable, n=1):
    l = len(iterable)
    for ndx in range(0, l, n):
        yield iterable[ndx:min(ndx + n, l)]

for x in batch(range(0, 10), 3):
    print x


リストを使った例

data = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # list of data 

for x in batch(data, 3):
    print(x)

# Output

[0, 1, 2]
[3, 4, 5]
[6, 7, 8]
[9, 10]

新しいリストの構築を避けることができます。