Source code for coinflip.randtests._collections

# TODO test non-ordered inputs, subclass OrderedDict
from typing import Iterable

__all__ = ["FloorDict", "RoundingDict", "Bins"]


[docs]class FloorDict(dict): """Subclassed `dict` where invalid keys floor to the smallest real key If a key is accessed that does not exist, the nearest real key that is the less-than of the passed key is used. """ def __missing__(self, key): prevkey = None for realkey, value in self.items(): if key < realkey: if prevkey is None: raise KeyError("Passed key smaller than all real keys") return super().__getitem__(prevkey) prevkey = realkey else: return super().__getitem__(prevkey)
[docs]class RoundingDict(dict): """Subclassed `dict` where invalid keys are rounded to the nearest real key If a key is accessed that does not exist, the nearest real key to the passed key is used. """ def _roundkey(self, key): realkeys = list(self.keys()) minkey = realkeys[0] midkeys = realkeys[1:-1] maxkey = realkeys[-1] if key <= minkey: return minkey elif key >= maxkey: return maxkey elif key in midkeys: return key else: raise KeyError() def __setitem__(self, key, value): realkey = self._roundkey(key) super().__setitem__(realkey, value) def __getitem__(self, key): realkey = self._roundkey(key) return super().__getitem__(realkey)
[docs]class Bins(RoundingDict): """Subclassed `RoundingDict` to initialise intervals as empty bins""" def __init__(self, intervals: Iterable[int]): """Initialise intervals as keys to values of 0""" empty_bins = {interval: 0 for interval in intervals} super().__init__(empty_bins)