In the session "recipes" module itertools
has a function called grouper
who picks up a sequence and iterates "to pieces":
from itertools import zip_longest
def grouper(iterable, n, fillvalue=None):
"Collect data into fixed-length chunks or blocks"
# grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx"
args = [iter(iterable)] * n
return zip_longest(*args, fillvalue=fillvalue)
teste = "77775698897897236"
for grupo in grouper(teste, 4, ''):
print("".join(grupo))
Code running on Repl.it
Upshot:
7777
5698
8978
9723
6
Edit
To answer that uses slicing is perfectly suitable for cases where the iterable is small, my answer becomes more effective if you are working with much larger sequence because there is no copy of parts of the iterable and it would also work when receiving any iterable, even if this does not support slicing.
Explanation
Starting with the line:
args = [iter(iterable)] * n
First of all:
- We create an object of the type
Iterator
using the method iter()
;
- A single element list is created, this element is the iterator created in the above item;
Multiply the list n
times for them to be created n
references at the same iterator (in this answer better explanation about sequence multiplication).
>>> [iter("77775698897897236")] * 4
[<str_iterator at 0x7f07473b4f10>,
<str_iterator at 0x7f07473b4f10>,
<str_iterator at 0x7f07473b4f10>,
<str_iterator at 0x7f07473b4f10>]
As you can see in item 3, we have a list with 4 references to the same iterator, as the four point to the same memory address (0x7f07473b4f10
).
That is, if I consume 1 item from each reference would be the same as consuming 4 items from the "original iterator".
>>> for iterador in [iter("1234567890")] * 4:
>>> next(iterador)
1
2
3
4
That’s where the itertools.zip_longest
, to consume these references to the same iterator. For when you do:
args = [iter("1234567890")] * 4
zip_longest(*args)
It would be the same as doing:
ref_iter = iter("1234567890")
zip_longest(ref_iter, ref_iter, ref_iter, ref_iter)
And in practice this code consumes the entire iterator of 4 in 4 items. The above code would return:
>>> ref_iter = iter("1234567890")
>>> zip_longest(ref_iter, ref_iter, ref_iter, ref_iter)
[('1', '2', '3', '4'), ('5', '6', '7', '8'), ('9', '0', None, None)]
Your suggestion is making a mistake
– Lucas Emanuel
I used a comma to separate the indexes, it should be two points.
– user172849
I edited the answer just because the variable
str
was overwriting the native python string and the spaces in the Slice to comply with PEP8. ;)– fernandosavio