def fill(iterable, fill_value=None, fill_value_maker=None, length=infinity, sequence_type=None, lazy_tuple=False): ''' Iterate on `iterable`, and after it's exhaused, yield fill values. If `fill_value_maker` is given, it's used to create fill values dynamically. (Useful if your fill value is `[]` and you don't want to use many copies of the same list.) If `length` is given, shortens the iterator to that length. If `sequence_type` is given, instead of returning an iterator, this function will return a sequence of that type. If `lazy_tuple=True`, uses a `LazyTuple`. (Can't use both options together.) ''' # Validating user input: assert (sequence_type is None) or (lazy_tuple is False) iterator = _fill(iterable, fill_value=fill_value, fill_value_maker=fill_value_maker, length=length) if lazy_tuple: from combi._python_toolbox import nifty_collections return nifty_collections.LazyTuple(iterator) elif sequence_type is None: return iterator else: return sequence_type(iterator)
def iterate_overlapping_subsequences(iterable, length=2, wrap_around=False, lazy_tuple=False): ''' Iterate over overlapping subsequences from the iterable. Example: if the iterable is [0, 1, 2, 3], then the result would be `[(0, 1), (1, 2), (2, 3)]`. (Except it would be an iterator and not an actual list.) With a length of 3, the result would be an iterator of `[(0, 1, 2), (1, 2, 3)]`. If `wrap_around=True`, the result would be `[(0, 1, 2), (1, 2, 3), (2, 3, 0), (3, 0, 1)]`. If `lazy_tuple=True`, returns a `LazyTuple` rather than an iterator. ''' iterator = _iterate_overlapping_subsequences(iterable=iterable, length=length, wrap_around=wrap_around) if lazy_tuple: from combi._python_toolbox import nifty_collections return nifty_collections.LazyTuple(iterator) else: return iterator
def _enumerate(iterable, reverse_index): if reverse_index is False: return __builtin__.enumerate(iterable) else: from combi._python_toolbox import sequence_tools try: length = sequence_tools.get_length(iterable) except AttributeError: iterable = nifty_collections.LazyTuple(iterable) length = len(iterable) return itertools.izip(range(length - 1, -1, -1), iterable)
def call_until_exception(function, exception, lazy_tuple=False): ''' Iterate on values returned from `function` until getting `exception`. If `lazy_tuple=True`, returns a `LazyTuple` rather than an iterator. ''' iterator = _call_until_exception(function, exception) if lazy_tuple: from combi._python_toolbox import nifty_collections return nifty_collections.LazyTuple(iterator) else: return iterator
def zip_non_equal(iterables, lazy_tuple=False): ''' Zip the iterables, but only yield the tuples where the items aren't equal. ''' from combi._python_toolbox import logic_tools iterator = (items for items in zip(*iterables) if not logic_tools.all_equivalent(items)) if lazy_tuple: from combi._python_toolbox import nifty_collections return nifty_collections.LazyTuple(iterator) else: return iterator
def iter_with(iterable, context_manager, lazy_tuple=False): ''' Iterate on `iterable`, `with`ing the context manager on every `next`. If `lazy_tuple=True`, returns a `LazyTuple` rather than an iterator. ''' iterator = _iter_with(iterable=iterable, context_manager=context_manager) if lazy_tuple: from combi._python_toolbox import nifty_collections return nifty_collections.LazyTuple(iterator) else: return iterator
def shorten(iterable, length, lazy_tuple=False): ''' Shorten an iterable to `length`. Iterate over the given iterable, but stop after `n` iterations (Or when the iterable stops iteration by itself.) `n` may be infinite. If `lazy_tuple=True`, returns a `LazyTuple` rather than an iterator. ''' iterator = _shorten(iterable=iterable, length=length) if lazy_tuple: from combi._python_toolbox import nifty_collections return nifty_collections.LazyTuple(iterator) else: return iterator
def enumerate(iterable, reverse_index=False, lazy_tuple=False): ''' Iterate over `(i, item)` pairs, where `i` is the index number of `item`. This is an extension of the builtin `enumerate`. What it allows is to get a reverse index, by specifying `reverse_index=True`. This causes `i` to count down to zero instead of up from zero, so the `i` of the last member will be zero. If `lazy_tuple=True`, returns a `LazyTuple` rather than an iterator. ''' iterator = _enumerate(iterable=iterable, reverse_index=reverse_index) if lazy_tuple: from combi._python_toolbox import nifty_collections return nifty_collections.LazyTuple(iterator) else: return iterator
def get_neighbors(self, *, degrees=(1, ), perm_space=None): ''' Get the neighbor permutations of this permutation. This means, get the permutations that are close to this permutation. By default, this means permutations that are one transformation (switching a pair of items) away from this permutation. You can specify a custom sequence of integers to the `degrees` argument to get different degrees of relation. (e.g. specify `degrees=(1, 2)` to get both the closest neighbors and the second-closest neighbors.) ''' from ..map_space import MapSpace if self.is_combination or self.is_recurrent or self.is_partial: raise NotImplementedError if perm_space is None: perm_space = self.nominal_perm_space return MapSpace( perm_space.coerce_perm, nifty_collections.LazyTuple( tuple(perm) for perm in PermSpace(self._perm_sequence, degrees=degrees) if tuple(perm) in perm_space))
def __init__(self, sequences): self.sequences = nifty_collections.LazyTuple( (sequence_tools.ensure_iterable_is_immutable_sequence( sequence, default_type=nifty_collections.LazyTuple) for sequence in sequences) )