Source code for fictive.patterns.iterables

"""
Common patterns for working with :term:`iterable` objects

"""

import collections.abc
import itertools
import typing


[docs]def chunks(input_: typing.Iterable, chunk_size: int): """ create an iterator that splits `input_` into objects of length `chunk_size` if `input_` is a `typing.Sequence`, the generated chunks will be slices of `input_`. Otherwise, the generated chunks will themselves be independent generators on `input_`. The last chunk will contain :code:`len(input_) % chunk_size` elements .. doctest:: :options: +NORMALIZE_WHITESPACE >>> from fictive.patterns.iterables import chunks >>> sample = 'spam and eggs' >>> chunks(sample, 5) <generator object chunks at ...> >>> for chunk in chunks(sample, 5): ... print(chunk) spam and e ggs >>> sample = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} >>> chunk_generators = list(chunks(sample, 4)) >>> chunk_generators [<itertools.islice object at ...>, \ <itertools.islice object at ...>, \ <itertools.islice object at ...>] >>> list(chunk_generators[2]) [9, 10] >>> list(chunk_generators[0]) [1, 2, 3, 4] """ if isinstance(input_, collections.abc.Sequence): while input_: chunk, input_ = input_[:chunk_size], input_[chunk_size:] yield chunk elif isinstance(input_, collections.abc.Iterator): try: while True: chunk, input_, test = itertools.tee(input_, 3) next(test) chunk = itertools.islice(chunk, 0, chunk_size) input_ = itertools.islice(input_, chunk_size, None) yield chunk except StopIteration: return else: for chunk in chunks((item for item in input_), chunk_size): yield chunk