2017-09-26 95 views
1

基本上,我想從給定列表l中創建一個無限生成器,其批量大小爲batch_size。舉例來說,如果我有l = [1, 2, 3, 4, 5]batch_size = 2名單,我想產生的[1, 2][3, 4][5, 1][2, 3]無限循環......(類似於itertool.circular使用附加批量大小)從列表中生成循環批次

我目前的做法是因爲在結束後不給予正確的解決方案還沒有我只是墊列表的第一個元素,當我到達終點:

l = [1, 2, 3, 4, 5] 

def generator(l, batch_size=2): 
    while 1: 
     for i in range(0, len(l), batch_size): 
      batch = l[i:(i + batch_size)] 
      if len(batch) < batch_size: 
       batch.extend(l[0: batch_size - len(batch)]) 
      yield batch 

>> gen = generator(l, batch_size=2) 
>> next(gen) # [1, 2] 
>> next(gen) # [3, 4] 
>> next(gen) # [5, 1] 
>> next(gen) # [1, 2] << want [2, 3] instead 

有沒有辦法做到這一點以循環方式?

回答

4

是的,你基本上要的 「取」 和cycle組合:

>>> def circle_batch(iterable, batchsize): 
...  it = itertools.cycle(iterable) 
...  while True: 
...   yield list(itertools.islice(it, batchsize)) 
... 
>>> l = [1, 2, 3, 4, 5] 
>>> c = circle_batch(l, 2) 
>>> next(c) 
[1, 2] 
>>> next(c) 
[3, 4] 
>>> next(c) 
[5, 1] 
>>> next(c) 
[2, 3] 
>>> next(c) 
[4, 5] 

recipes in the docs你會看到take是一個基本的工具,因此使用:

>>> def take(n, iterable): 
...  "Return first n items of the iterable as a list" 
...  return list(islice(iterable, n)) 
... 
>>> def cycle_batch(iterable, batchsize): 
...  it = itertools.cycle(iterable) 
...  while True: 
...   return take(batchsize, it) 
... 
>>> l = [1, 2, 3, 4, 5] 
>>> c = circle_batch(l, 2) 
>>> next(c) 
[1, 2] 
>>> next(c) 
[3, 4] 
>>> next(c) 
[5, 1] 
>>> next(c) 
[2, 3] 
>>> next(c) 
[4, 5] 
>>> next(c) 
[1, 2] 
+2

爲什麼分配給'x' ... –

+0

@MosesKoledoye沒有好的重新不久,我可以刪除它 –

+0

謝謝@ juanpa.arrivillaga!這很好地工作(在接受解決方案之前必須5分鐘)。 – titipata

3

這應該工作:

def generator(l, batch_size=2): 
    gen = iter(itertools.cycle(l)) 
    while 1: 
     yield [next(gen) for _ in range(batch_size)] 

gen = generator(l, batch_size=2) 
+0

謝謝@schwobaseggl!這很好。我必須接受@ juanpa.arrivillaga壽,但這兩種解決方案對我來說:) – titipata

+0

也許你打算'循環'而不是'圈'? – titipata