Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
_itertools.py172 linesDownload Raw Back to importlib_metadata
1from collections import defaultdict, deque2from itertools import filterfalse3 4 5def unique_everseen(iterable, key=None):6    "List unique elements, preserving order. Remember all elements ever seen."7    # unique_everseen('AAAABBBCCDAABBB') --> A B C D8    # unique_everseen('ABBCcAD', str.lower) --> A B C D9    seen = set()10    seen_add = seen.add11    if key is None:12        for element in filterfalse(seen.__contains__, iterable):13            seen_add(element)14            yield element15    else:16        for element in iterable:17            k = key(element)18            if k not in seen:19                seen_add(k)20                yield element21 22 23# copied from more_itertools 8.824def always_iterable(obj, base_type=(str, bytes)):25    """If *obj* is iterable, return an iterator over its items::26 27        >>> obj = (1, 2, 3)28        >>> list(always_iterable(obj))29        [1, 2, 3]30 31    If *obj* is not iterable, return a one-item iterable containing *obj*::32 33        >>> obj = 134        >>> list(always_iterable(obj))35        [1]36 37    If *obj* is ``None``, return an empty iterable:38 39        >>> obj = None40        >>> list(always_iterable(None))41        []42 43    By default, binary and text strings are not considered iterable::44 45        >>> obj = 'foo'46        >>> list(always_iterable(obj))47        ['foo']48 49    If *base_type* is set, objects for which ``isinstance(obj, base_type)``50    returns ``True`` won't be considered iterable.51 52        >>> obj = {'a': 1}53        >>> list(always_iterable(obj))  # Iterate over the dict's keys54        ['a']55        >>> list(always_iterable(obj, base_type=dict))  # Treat dicts as a unit56        [{'a': 1}]57 58    Set *base_type* to ``None`` to avoid any special handling and treat objects59    Python considers iterable as iterable:60 61        >>> obj = 'foo'62        >>> list(always_iterable(obj, base_type=None))63        ['f', 'o', 'o']64    """65    if obj is None:66        return iter(())67 68    if (base_type is not None) and isinstance(obj, base_type):69        return iter((obj,))70 71    try:72        return iter(obj)73    except TypeError:74        return iter((obj,))75 76 77# Copied from more_itertools 10.378class bucket:79    """Wrap *iterable* and return an object that buckets the iterable into80    child iterables based on a *key* function.81 82        >>> iterable = ['a1', 'b1', 'c1', 'a2', 'b2', 'c2', 'b3']83        >>> s = bucket(iterable, key=lambda x: x[0])  # Bucket by 1st character84        >>> sorted(list(s))  # Get the keys85        ['a', 'b', 'c']86        >>> a_iterable = s['a']87        >>> next(a_iterable)88        'a1'89        >>> next(a_iterable)90        'a2'91        >>> list(s['b'])92        ['b1', 'b2', 'b3']93 94    The original iterable will be advanced and its items will be cached until95    they are used by the child iterables. This may require significant storage.96 97    By default, attempting to select a bucket to which no items belong  will98    exhaust the iterable and cache all values.99    If you specify a *validator* function, selected buckets will instead be100    checked against it.101 102        >>> from itertools import count103        >>> it = count(1, 2)  # Infinite sequence of odd numbers104        >>> key = lambda x: x % 10  # Bucket by last digit105        >>> validator = lambda x: x in {1, 3, 5, 7, 9}  # Odd digits only106        >>> s = bucket(it, key=key, validator=validator)107        >>> 2 in s108        False109        >>> list(s[2])110        []111 112    """113 114    def __init__(self, iterable, key, validator=None):115        self._it = iter(iterable)116        self._key = key117        self._cache = defaultdict(deque)118        self._validator = validator or (lambda x: True)119 120    def __contains__(self, value):121        if not self._validator(value):122            return False123 124        try:125            item = next(self[value])126        except StopIteration:127            return False128        else:129            self._cache[value].appendleft(item)130 131        return True132 133    def _get_values(self, value):134        """135        Helper to yield items from the parent iterator that match *value*.136        Items that don't match are stored in the local cache as they137        are encountered.138        """139        while True:140            # If we've cached some items that match the target value, emit141            # the first one and evict it from the cache.142            if self._cache[value]:143                yield self._cache[value].popleft()144            # Otherwise we need to advance the parent iterator to search for145            # a matching item, caching the rest.146            else:147                while True:148                    try:149                        item = next(self._it)150                    except StopIteration:151                        return152                    item_value = self._key(item)153                    if item_value == value:154                        yield item155                        break156                    elif self._validator(item_value):157                        self._cache[item_value].append(item)158 159    def __iter__(self):160        for item in self._it:161            item_value = self._key(item)162            if self._validator(item_value):163                self._cache[item_value].append(item)164 165        yield from self._cache.keys()166 167    def __getitem__(self, value):168        if not self._validator(value):169            return iter(())170 171        return self._get_values(value)172 
codekingpro/portable-devtools · Team Ai