Reputation: 544
My problem was that I needed to deliver batches from an itertools.cycle
generator in list form.
A cycle
takes an iterable and loops it around itself indefinitely. For example:
>>> my_cycle = itertools.cycle('abc')
>>> next(my_cycle)
'a'
>>> next(my_cycle)
'b'
>>> next(my_cycle)
'c'
>>> next(my_cycle)
'a'
And so on.
The question becomes, how do we deliver a list of batch length n
from a cyclic generator, while preserving where we are in the cycle?
Desired output is:
c = itertools.cycle('abc')
batch_size = 2
Out[0]: ['a', 'b']
Out[1]: ['c', 'a']
Out[2]: ['b', 'c']
I am posting my solution in case someone runs into the same problem.
Upvotes: 1
Views: 727
Reputation: 3372
It seems like islice
was made for this:
>>> from itertools import cycle, islice
>>> size_of_batch = 5
>>> c = cycle('abcdefg')
>>> list(islice(c, size_of_batch))
['a', 'b', 'c', 'd', 'e']
>>> list(islice(c, size_of_batch))
['f', 'g', 'a', 'b', 'c']
Upvotes: 6
Reputation: 44525
There is an itertools recipe designed for this:
from itertools import islice, cycle
def take(n, iterable):
"Return first n items of the iterable as a list"
return list(islice(iterable, n))
c = cycle("abcdefg")
take(5, c)
# ['a', 'b', 'c', 'd', 'e']
Upvotes: 3
Reputation: 544
>>> size_of_batch = 5
>>> c = itertools.cycle('abcdefg')
>>> [next(c) for _ in range(size_of_batch)]
['a', 'b', 'c', 'd', 'e']
>>> [next(c) for _ in range(size_of_batch)]
['f', 'g', 'a', 'b', 'c']
Upvotes: 4