Updated script that can be controled by Nodejs web app
This commit is contained in:
74
lib/python3.13/site-packages/sortedcontainers/__init__.py
Normal file
74
lib/python3.13/site-packages/sortedcontainers/__init__.py
Normal file
@ -0,0 +1,74 @@
|
||||
"""Sorted Containers -- Sorted List, Sorted Dict, Sorted Set
|
||||
|
||||
Sorted Containers is an Apache2 licensed containers library, written in
|
||||
pure-Python, and fast as C-extensions.
|
||||
|
||||
Python's standard library is great until you need a sorted collections
|
||||
type. Many will attest that you can get really far without one, but the moment
|
||||
you **really need** a sorted list, dict, or set, you're faced with a dozen
|
||||
different implementations, most using C-extensions without great documentation
|
||||
and benchmarking.
|
||||
|
||||
In Python, we can do better. And we can do it in pure-Python!
|
||||
|
||||
::
|
||||
|
||||
>>> from sortedcontainers import SortedList
|
||||
>>> sl = SortedList(['e', 'a', 'c', 'd', 'b'])
|
||||
>>> sl
|
||||
SortedList(['a', 'b', 'c', 'd', 'e'])
|
||||
>>> sl *= 1000000
|
||||
>>> sl.count('c')
|
||||
1000000
|
||||
>>> sl[-3:]
|
||||
['e', 'e', 'e']
|
||||
>>> from sortedcontainers import SortedDict
|
||||
>>> sd = SortedDict({'c': 3, 'a': 1, 'b': 2})
|
||||
>>> sd
|
||||
SortedDict({'a': 1, 'b': 2, 'c': 3})
|
||||
>>> sd.popitem(index=-1)
|
||||
('c', 3)
|
||||
>>> from sortedcontainers import SortedSet
|
||||
>>> ss = SortedSet('abracadabra')
|
||||
>>> ss
|
||||
SortedSet(['a', 'b', 'c', 'd', 'r'])
|
||||
>>> ss.bisect_left('c')
|
||||
2
|
||||
|
||||
Sorted Containers takes all of the work out of Python sorted types - making
|
||||
your deployment and use of Python easy. There's no need to install a C compiler
|
||||
or pre-build and distribute custom extensions. Performance is a feature and
|
||||
testing has 100% coverage with unit tests and hours of stress.
|
||||
|
||||
:copyright: (c) 2014-2019 by Grant Jenks.
|
||||
:license: Apache 2.0, see LICENSE for more details.
|
||||
|
||||
"""
|
||||
|
||||
|
||||
from .sortedlist import SortedList, SortedKeyList, SortedListWithKey
|
||||
from .sortedset import SortedSet
|
||||
from .sorteddict import (
|
||||
SortedDict,
|
||||
SortedKeysView,
|
||||
SortedItemsView,
|
||||
SortedValuesView,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
'SortedList',
|
||||
'SortedKeyList',
|
||||
'SortedListWithKey',
|
||||
'SortedDict',
|
||||
'SortedKeysView',
|
||||
'SortedItemsView',
|
||||
'SortedValuesView',
|
||||
'SortedSet',
|
||||
]
|
||||
|
||||
__title__ = 'sortedcontainers'
|
||||
__version__ = '2.4.0'
|
||||
__build__ = 0x020400
|
||||
__author__ = 'Grant Jenks'
|
||||
__license__ = 'Apache 2.0'
|
||||
__copyright__ = '2014-2019, Grant Jenks'
|
812
lib/python3.13/site-packages/sortedcontainers/sorteddict.py
Normal file
812
lib/python3.13/site-packages/sortedcontainers/sorteddict.py
Normal file
@ -0,0 +1,812 @@
|
||||
"""Sorted Dict
|
||||
==============
|
||||
|
||||
:doc:`Sorted Containers<index>` is an Apache2 licensed Python sorted
|
||||
collections library, written in pure-Python, and fast as C-extensions. The
|
||||
:doc:`introduction<introduction>` is the best way to get started.
|
||||
|
||||
Sorted dict implementations:
|
||||
|
||||
.. currentmodule:: sortedcontainers
|
||||
|
||||
* :class:`SortedDict`
|
||||
* :class:`SortedKeysView`
|
||||
* :class:`SortedItemsView`
|
||||
* :class:`SortedValuesView`
|
||||
|
||||
"""
|
||||
|
||||
import sys
|
||||
import warnings
|
||||
|
||||
from itertools import chain
|
||||
|
||||
from .sortedlist import SortedList, recursive_repr
|
||||
from .sortedset import SortedSet
|
||||
|
||||
###############################################################################
|
||||
# BEGIN Python 2/3 Shims
|
||||
###############################################################################
|
||||
|
||||
try:
|
||||
from collections.abc import (
|
||||
ItemsView, KeysView, Mapping, ValuesView, Sequence
|
||||
)
|
||||
except ImportError:
|
||||
from collections import ItemsView, KeysView, Mapping, ValuesView, Sequence
|
||||
|
||||
###############################################################################
|
||||
# END Python 2/3 Shims
|
||||
###############################################################################
|
||||
|
||||
|
||||
class SortedDict(dict):
|
||||
"""Sorted dict is a sorted mutable mapping.
|
||||
|
||||
Sorted dict keys are maintained in sorted order. The design of sorted dict
|
||||
is simple: sorted dict inherits from dict to store items and maintains a
|
||||
sorted list of keys.
|
||||
|
||||
Sorted dict keys must be hashable and comparable. The hash and total
|
||||
ordering of keys must not change while they are stored in the sorted dict.
|
||||
|
||||
Mutable mapping methods:
|
||||
|
||||
* :func:`SortedDict.__getitem__` (inherited from dict)
|
||||
* :func:`SortedDict.__setitem__`
|
||||
* :func:`SortedDict.__delitem__`
|
||||
* :func:`SortedDict.__iter__`
|
||||
* :func:`SortedDict.__len__` (inherited from dict)
|
||||
|
||||
Methods for adding items:
|
||||
|
||||
* :func:`SortedDict.setdefault`
|
||||
* :func:`SortedDict.update`
|
||||
|
||||
Methods for removing items:
|
||||
|
||||
* :func:`SortedDict.clear`
|
||||
* :func:`SortedDict.pop`
|
||||
* :func:`SortedDict.popitem`
|
||||
|
||||
Methods for looking up items:
|
||||
|
||||
* :func:`SortedDict.__contains__` (inherited from dict)
|
||||
* :func:`SortedDict.get` (inherited from dict)
|
||||
* :func:`SortedDict.peekitem`
|
||||
|
||||
Methods for views:
|
||||
|
||||
* :func:`SortedDict.keys`
|
||||
* :func:`SortedDict.items`
|
||||
* :func:`SortedDict.values`
|
||||
|
||||
Methods for miscellany:
|
||||
|
||||
* :func:`SortedDict.copy`
|
||||
* :func:`SortedDict.fromkeys`
|
||||
* :func:`SortedDict.__reversed__`
|
||||
* :func:`SortedDict.__eq__` (inherited from dict)
|
||||
* :func:`SortedDict.__ne__` (inherited from dict)
|
||||
* :func:`SortedDict.__repr__`
|
||||
* :func:`SortedDict._check`
|
||||
|
||||
Sorted list methods available (applies to keys):
|
||||
|
||||
* :func:`SortedList.bisect_left`
|
||||
* :func:`SortedList.bisect_right`
|
||||
* :func:`SortedList.count`
|
||||
* :func:`SortedList.index`
|
||||
* :func:`SortedList.irange`
|
||||
* :func:`SortedList.islice`
|
||||
* :func:`SortedList._reset`
|
||||
|
||||
Additional sorted list methods available, if key-function used:
|
||||
|
||||
* :func:`SortedKeyList.bisect_key_left`
|
||||
* :func:`SortedKeyList.bisect_key_right`
|
||||
* :func:`SortedKeyList.irange_key`
|
||||
|
||||
Sorted dicts may only be compared for equality and inequality.
|
||||
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Initialize sorted dict instance.
|
||||
|
||||
Optional key-function argument defines a callable that, like the `key`
|
||||
argument to the built-in `sorted` function, extracts a comparison key
|
||||
from each dictionary key. If no function is specified, the default
|
||||
compares the dictionary keys directly. The key-function argument must
|
||||
be provided as a positional argument and must come before all other
|
||||
arguments.
|
||||
|
||||
Optional iterable argument provides an initial sequence of pairs to
|
||||
initialize the sorted dict. Each pair in the sequence defines the key
|
||||
and corresponding value. If a key is seen more than once, the last
|
||||
value associated with it is stored in the new sorted dict.
|
||||
|
||||
Optional mapping argument provides an initial mapping of items to
|
||||
initialize the sorted dict.
|
||||
|
||||
If keyword arguments are given, the keywords themselves, with their
|
||||
associated values, are added as items to the dictionary. If a key is
|
||||
specified both in the positional argument and as a keyword argument,
|
||||
the value associated with the keyword is stored in the
|
||||
sorted dict.
|
||||
|
||||
Sorted dict keys must be hashable, per the requirement for Python's
|
||||
dictionaries. Keys (or the result of the key-function) must also be
|
||||
comparable, per the requirement for sorted lists.
|
||||
|
||||
>>> d = {'alpha': 1, 'beta': 2}
|
||||
>>> SortedDict([('alpha', 1), ('beta', 2)]) == d
|
||||
True
|
||||
>>> SortedDict({'alpha': 1, 'beta': 2}) == d
|
||||
True
|
||||
>>> SortedDict(alpha=1, beta=2) == d
|
||||
True
|
||||
|
||||
"""
|
||||
if args and (args[0] is None or callable(args[0])):
|
||||
_key = self._key = args[0]
|
||||
args = args[1:]
|
||||
else:
|
||||
_key = self._key = None
|
||||
|
||||
self._list = SortedList(key=_key)
|
||||
|
||||
# Reaching through ``self._list`` repeatedly adds unnecessary overhead
|
||||
# so cache references to sorted list methods.
|
||||
|
||||
_list = self._list
|
||||
self._list_add = _list.add
|
||||
self._list_clear = _list.clear
|
||||
self._list_iter = _list.__iter__
|
||||
self._list_reversed = _list.__reversed__
|
||||
self._list_pop = _list.pop
|
||||
self._list_remove = _list.remove
|
||||
self._list_update = _list.update
|
||||
|
||||
# Expose some sorted list methods publicly.
|
||||
|
||||
self.bisect_left = _list.bisect_left
|
||||
self.bisect = _list.bisect_right
|
||||
self.bisect_right = _list.bisect_right
|
||||
self.index = _list.index
|
||||
self.irange = _list.irange
|
||||
self.islice = _list.islice
|
||||
self._reset = _list._reset
|
||||
|
||||
if _key is not None:
|
||||
self.bisect_key_left = _list.bisect_key_left
|
||||
self.bisect_key_right = _list.bisect_key_right
|
||||
self.bisect_key = _list.bisect_key
|
||||
self.irange_key = _list.irange_key
|
||||
|
||||
self._update(*args, **kwargs)
|
||||
|
||||
|
||||
@property
|
||||
def key(self):
|
||||
"""Function used to extract comparison key from keys.
|
||||
|
||||
Sorted dict compares keys directly when the key function is none.
|
||||
|
||||
"""
|
||||
return self._key
|
||||
|
||||
|
||||
@property
|
||||
def iloc(self):
|
||||
"""Cached reference of sorted keys view.
|
||||
|
||||
Deprecated in version 2 of Sorted Containers. Use
|
||||
:func:`SortedDict.keys` instead.
|
||||
|
||||
"""
|
||||
# pylint: disable=attribute-defined-outside-init
|
||||
try:
|
||||
return self._iloc
|
||||
except AttributeError:
|
||||
warnings.warn(
|
||||
'sorted_dict.iloc is deprecated.'
|
||||
' Use SortedDict.keys() instead.',
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
_iloc = self._iloc = SortedKeysView(self)
|
||||
return _iloc
|
||||
|
||||
|
||||
def clear(self):
|
||||
|
||||
"""Remove all items from sorted dict.
|
||||
|
||||
Runtime complexity: `O(n)`
|
||||
|
||||
"""
|
||||
dict.clear(self)
|
||||
self._list_clear()
|
||||
|
||||
|
||||
def __delitem__(self, key):
|
||||
"""Remove item from sorted dict identified by `key`.
|
||||
|
||||
``sd.__delitem__(key)`` <==> ``del sd[key]``
|
||||
|
||||
Runtime complexity: `O(log(n))` -- approximate.
|
||||
|
||||
>>> sd = SortedDict({'a': 1, 'b': 2, 'c': 3})
|
||||
>>> del sd['b']
|
||||
>>> sd
|
||||
SortedDict({'a': 1, 'c': 3})
|
||||
>>> del sd['z']
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
KeyError: 'z'
|
||||
|
||||
:param key: `key` for item lookup
|
||||
:raises KeyError: if key not found
|
||||
|
||||
"""
|
||||
dict.__delitem__(self, key)
|
||||
self._list_remove(key)
|
||||
|
||||
|
||||
def __iter__(self):
|
||||
"""Return an iterator over the keys of the sorted dict.
|
||||
|
||||
``sd.__iter__()`` <==> ``iter(sd)``
|
||||
|
||||
Iterating the sorted dict while adding or deleting items may raise a
|
||||
:exc:`RuntimeError` or fail to iterate over all keys.
|
||||
|
||||
"""
|
||||
return self._list_iter()
|
||||
|
||||
|
||||
def __reversed__(self):
|
||||
"""Return a reverse iterator over the keys of the sorted dict.
|
||||
|
||||
``sd.__reversed__()`` <==> ``reversed(sd)``
|
||||
|
||||
Iterating the sorted dict while adding or deleting items may raise a
|
||||
:exc:`RuntimeError` or fail to iterate over all keys.
|
||||
|
||||
"""
|
||||
return self._list_reversed()
|
||||
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
"""Store item in sorted dict with `key` and corresponding `value`.
|
||||
|
||||
``sd.__setitem__(key, value)`` <==> ``sd[key] = value``
|
||||
|
||||
Runtime complexity: `O(log(n))` -- approximate.
|
||||
|
||||
>>> sd = SortedDict()
|
||||
>>> sd['c'] = 3
|
||||
>>> sd['a'] = 1
|
||||
>>> sd['b'] = 2
|
||||
>>> sd
|
||||
SortedDict({'a': 1, 'b': 2, 'c': 3})
|
||||
|
||||
:param key: key for item
|
||||
:param value: value for item
|
||||
|
||||
"""
|
||||
if key not in self:
|
||||
self._list_add(key)
|
||||
dict.__setitem__(self, key, value)
|
||||
|
||||
_setitem = __setitem__
|
||||
|
||||
|
||||
def __or__(self, other):
|
||||
if not isinstance(other, Mapping):
|
||||
return NotImplemented
|
||||
items = chain(self.items(), other.items())
|
||||
return self.__class__(self._key, items)
|
||||
|
||||
|
||||
def __ror__(self, other):
|
||||
if not isinstance(other, Mapping):
|
||||
return NotImplemented
|
||||
items = chain(other.items(), self.items())
|
||||
return self.__class__(self._key, items)
|
||||
|
||||
|
||||
def __ior__(self, other):
|
||||
self._update(other)
|
||||
return self
|
||||
|
||||
|
||||
def copy(self):
|
||||
"""Return a shallow copy of the sorted dict.
|
||||
|
||||
Runtime complexity: `O(n)`
|
||||
|
||||
:return: new sorted dict
|
||||
|
||||
"""
|
||||
return self.__class__(self._key, self.items())
|
||||
|
||||
__copy__ = copy
|
||||
|
||||
|
||||
@classmethod
|
||||
def fromkeys(cls, iterable, value=None):
|
||||
"""Return a new sorted dict initailized from `iterable` and `value`.
|
||||
|
||||
Items in the sorted dict have keys from `iterable` and values equal to
|
||||
`value`.
|
||||
|
||||
Runtime complexity: `O(n*log(n))`
|
||||
|
||||
:return: new sorted dict
|
||||
|
||||
"""
|
||||
return cls((key, value) for key in iterable)
|
||||
|
||||
|
||||
def keys(self):
|
||||
"""Return new sorted keys view of the sorted dict's keys.
|
||||
|
||||
See :class:`SortedKeysView` for details.
|
||||
|
||||
:return: new sorted keys view
|
||||
|
||||
"""
|
||||
return SortedKeysView(self)
|
||||
|
||||
|
||||
def items(self):
|
||||
"""Return new sorted items view of the sorted dict's items.
|
||||
|
||||
See :class:`SortedItemsView` for details.
|
||||
|
||||
:return: new sorted items view
|
||||
|
||||
"""
|
||||
return SortedItemsView(self)
|
||||
|
||||
|
||||
def values(self):
|
||||
"""Return new sorted values view of the sorted dict's values.
|
||||
|
||||
See :class:`SortedValuesView` for details.
|
||||
|
||||
:return: new sorted values view
|
||||
|
||||
"""
|
||||
return SortedValuesView(self)
|
||||
|
||||
|
||||
if sys.hexversion < 0x03000000:
|
||||
def __make_raise_attributeerror(original, alternate):
|
||||
# pylint: disable=no-self-argument
|
||||
message = (
|
||||
'SortedDict.{original}() is not implemented.'
|
||||
' Use SortedDict.{alternate}() instead.'
|
||||
).format(original=original, alternate=alternate)
|
||||
def method(self):
|
||||
# pylint: disable=missing-docstring,unused-argument
|
||||
raise AttributeError(message)
|
||||
method.__name__ = original # pylint: disable=non-str-assignment-to-dunder-name
|
||||
method.__doc__ = message
|
||||
return property(method)
|
||||
|
||||
iteritems = __make_raise_attributeerror('iteritems', 'items')
|
||||
iterkeys = __make_raise_attributeerror('iterkeys', 'keys')
|
||||
itervalues = __make_raise_attributeerror('itervalues', 'values')
|
||||
viewitems = __make_raise_attributeerror('viewitems', 'items')
|
||||
viewkeys = __make_raise_attributeerror('viewkeys', 'keys')
|
||||
viewvalues = __make_raise_attributeerror('viewvalues', 'values')
|
||||
|
||||
|
||||
class _NotGiven(object):
|
||||
# pylint: disable=too-few-public-methods
|
||||
def __repr__(self):
|
||||
return '<not-given>'
|
||||
|
||||
__not_given = _NotGiven()
|
||||
|
||||
def pop(self, key, default=__not_given):
|
||||
"""Remove and return value for item identified by `key`.
|
||||
|
||||
If the `key` is not found then return `default` if given. If `default`
|
||||
is not given then raise :exc:`KeyError`.
|
||||
|
||||
Runtime complexity: `O(log(n))` -- approximate.
|
||||
|
||||
>>> sd = SortedDict({'a': 1, 'b': 2, 'c': 3})
|
||||
>>> sd.pop('c')
|
||||
3
|
||||
>>> sd.pop('z', 26)
|
||||
26
|
||||
>>> sd.pop('y')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
KeyError: 'y'
|
||||
|
||||
:param key: `key` for item
|
||||
:param default: `default` value if key not found (optional)
|
||||
:return: value for item
|
||||
:raises KeyError: if `key` not found and `default` not given
|
||||
|
||||
"""
|
||||
if key in self:
|
||||
self._list_remove(key)
|
||||
return dict.pop(self, key)
|
||||
else:
|
||||
if default is self.__not_given:
|
||||
raise KeyError(key)
|
||||
return default
|
||||
|
||||
|
||||
def popitem(self, index=-1):
|
||||
"""Remove and return ``(key, value)`` pair at `index` from sorted dict.
|
||||
|
||||
Optional argument `index` defaults to -1, the last item in the sorted
|
||||
dict. Specify ``index=0`` for the first item in the sorted dict.
|
||||
|
||||
If the sorted dict is empty, raises :exc:`KeyError`.
|
||||
|
||||
If the `index` is out of range, raises :exc:`IndexError`.
|
||||
|
||||
Runtime complexity: `O(log(n))`
|
||||
|
||||
>>> sd = SortedDict({'a': 1, 'b': 2, 'c': 3})
|
||||
>>> sd.popitem()
|
||||
('c', 3)
|
||||
>>> sd.popitem(0)
|
||||
('a', 1)
|
||||
>>> sd.popitem(100)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
IndexError: list index out of range
|
||||
|
||||
:param int index: `index` of item (default -1)
|
||||
:return: key and value pair
|
||||
:raises KeyError: if sorted dict is empty
|
||||
:raises IndexError: if `index` out of range
|
||||
|
||||
"""
|
||||
if not self:
|
||||
raise KeyError('popitem(): dictionary is empty')
|
||||
|
||||
key = self._list_pop(index)
|
||||
value = dict.pop(self, key)
|
||||
return (key, value)
|
||||
|
||||
|
||||
def peekitem(self, index=-1):
|
||||
"""Return ``(key, value)`` pair at `index` in sorted dict.
|
||||
|
||||
Optional argument `index` defaults to -1, the last item in the sorted
|
||||
dict. Specify ``index=0`` for the first item in the sorted dict.
|
||||
|
||||
Unlike :func:`SortedDict.popitem`, the sorted dict is not modified.
|
||||
|
||||
If the `index` is out of range, raises :exc:`IndexError`.
|
||||
|
||||
Runtime complexity: `O(log(n))`
|
||||
|
||||
>>> sd = SortedDict({'a': 1, 'b': 2, 'c': 3})
|
||||
>>> sd.peekitem()
|
||||
('c', 3)
|
||||
>>> sd.peekitem(0)
|
||||
('a', 1)
|
||||
>>> sd.peekitem(100)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
IndexError: list index out of range
|
||||
|
||||
:param int index: index of item (default -1)
|
||||
:return: key and value pair
|
||||
:raises IndexError: if `index` out of range
|
||||
|
||||
"""
|
||||
key = self._list[index]
|
||||
return key, self[key]
|
||||
|
||||
|
||||
def setdefault(self, key, default=None):
|
||||
"""Return value for item identified by `key` in sorted dict.
|
||||
|
||||
If `key` is in the sorted dict then return its value. If `key` is not
|
||||
in the sorted dict then insert `key` with value `default` and return
|
||||
`default`.
|
||||
|
||||
Optional argument `default` defaults to none.
|
||||
|
||||
Runtime complexity: `O(log(n))` -- approximate.
|
||||
|
||||
>>> sd = SortedDict()
|
||||
>>> sd.setdefault('a', 1)
|
||||
1
|
||||
>>> sd.setdefault('a', 10)
|
||||
1
|
||||
>>> sd
|
||||
SortedDict({'a': 1})
|
||||
|
||||
:param key: key for item
|
||||
:param default: value for item (default None)
|
||||
:return: value for item identified by `key`
|
||||
|
||||
"""
|
||||
if key in self:
|
||||
return self[key]
|
||||
dict.__setitem__(self, key, default)
|
||||
self._list_add(key)
|
||||
return default
|
||||
|
||||
|
||||
def update(self, *args, **kwargs):
|
||||
"""Update sorted dict with items from `args` and `kwargs`.
|
||||
|
||||
Overwrites existing items.
|
||||
|
||||
Optional arguments `args` and `kwargs` may be a mapping, an iterable of
|
||||
pairs or keyword arguments. See :func:`SortedDict.__init__` for
|
||||
details.
|
||||
|
||||
:param args: mapping or iterable of pairs
|
||||
:param kwargs: keyword arguments mapping
|
||||
|
||||
"""
|
||||
if not self:
|
||||
dict.update(self, *args, **kwargs)
|
||||
self._list_update(dict.__iter__(self))
|
||||
return
|
||||
|
||||
if not kwargs and len(args) == 1 and isinstance(args[0], dict):
|
||||
pairs = args[0]
|
||||
else:
|
||||
pairs = dict(*args, **kwargs)
|
||||
|
||||
if (10 * len(pairs)) > len(self):
|
||||
dict.update(self, pairs)
|
||||
self._list_clear()
|
||||
self._list_update(dict.__iter__(self))
|
||||
else:
|
||||
for key in pairs:
|
||||
self._setitem(key, pairs[key])
|
||||
|
||||
_update = update
|
||||
|
||||
|
||||
def __reduce__(self):
|
||||
"""Support for pickle.
|
||||
|
||||
The tricks played with caching references in
|
||||
:func:`SortedDict.__init__` confuse pickle so customize the reducer.
|
||||
|
||||
"""
|
||||
items = dict.copy(self)
|
||||
return (type(self), (self._key, items))
|
||||
|
||||
|
||||
@recursive_repr()
|
||||
def __repr__(self):
|
||||
"""Return string representation of sorted dict.
|
||||
|
||||
``sd.__repr__()`` <==> ``repr(sd)``
|
||||
|
||||
:return: string representation
|
||||
|
||||
"""
|
||||
_key = self._key
|
||||
type_name = type(self).__name__
|
||||
key_arg = '' if _key is None else '{0!r}, '.format(_key)
|
||||
item_format = '{0!r}: {1!r}'.format
|
||||
items = ', '.join(item_format(key, self[key]) for key in self._list)
|
||||
return '{0}({1}{{{2}}})'.format(type_name, key_arg, items)
|
||||
|
||||
|
||||
def _check(self):
|
||||
"""Check invariants of sorted dict.
|
||||
|
||||
Runtime complexity: `O(n)`
|
||||
|
||||
"""
|
||||
_list = self._list
|
||||
_list._check()
|
||||
assert len(self) == len(_list)
|
||||
assert all(key in self for key in _list)
|
||||
|
||||
|
||||
def _view_delitem(self, index):
|
||||
"""Remove item at `index` from sorted dict.
|
||||
|
||||
``view.__delitem__(index)`` <==> ``del view[index]``
|
||||
|
||||
Supports slicing.
|
||||
|
||||
Runtime complexity: `O(log(n))` -- approximate.
|
||||
|
||||
>>> sd = SortedDict({'a': 1, 'b': 2, 'c': 3})
|
||||
>>> view = sd.keys()
|
||||
>>> del view[0]
|
||||
>>> sd
|
||||
SortedDict({'b': 2, 'c': 3})
|
||||
>>> del view[-1]
|
||||
>>> sd
|
||||
SortedDict({'b': 2})
|
||||
>>> del view[:]
|
||||
>>> sd
|
||||
SortedDict({})
|
||||
|
||||
:param index: integer or slice for indexing
|
||||
:raises IndexError: if index out of range
|
||||
|
||||
"""
|
||||
_mapping = self._mapping
|
||||
_list = _mapping._list
|
||||
dict_delitem = dict.__delitem__
|
||||
if isinstance(index, slice):
|
||||
keys = _list[index]
|
||||
del _list[index]
|
||||
for key in keys:
|
||||
dict_delitem(_mapping, key)
|
||||
else:
|
||||
key = _list.pop(index)
|
||||
dict_delitem(_mapping, key)
|
||||
|
||||
|
||||
class SortedKeysView(KeysView, Sequence):
|
||||
"""Sorted keys view is a dynamic view of the sorted dict's keys.
|
||||
|
||||
When the sorted dict's keys change, the view reflects those changes.
|
||||
|
||||
The keys view implements the set and sequence abstract base classes.
|
||||
|
||||
"""
|
||||
__slots__ = ()
|
||||
|
||||
|
||||
@classmethod
|
||||
def _from_iterable(cls, it):
|
||||
return SortedSet(it)
|
||||
|
||||
|
||||
def __getitem__(self, index):
|
||||
"""Lookup key at `index` in sorted keys views.
|
||||
|
||||
``skv.__getitem__(index)`` <==> ``skv[index]``
|
||||
|
||||
Supports slicing.
|
||||
|
||||
Runtime complexity: `O(log(n))` -- approximate.
|
||||
|
||||
>>> sd = SortedDict({'a': 1, 'b': 2, 'c': 3})
|
||||
>>> skv = sd.keys()
|
||||
>>> skv[0]
|
||||
'a'
|
||||
>>> skv[-1]
|
||||
'c'
|
||||
>>> skv[:]
|
||||
['a', 'b', 'c']
|
||||
>>> skv[100]
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
IndexError: list index out of range
|
||||
|
||||
:param index: integer or slice for indexing
|
||||
:return: key or list of keys
|
||||
:raises IndexError: if index out of range
|
||||
|
||||
"""
|
||||
return self._mapping._list[index]
|
||||
|
||||
|
||||
__delitem__ = _view_delitem
|
||||
|
||||
|
||||
class SortedItemsView(ItemsView, Sequence):
|
||||
"""Sorted items view is a dynamic view of the sorted dict's items.
|
||||
|
||||
When the sorted dict's items change, the view reflects those changes.
|
||||
|
||||
The items view implements the set and sequence abstract base classes.
|
||||
|
||||
"""
|
||||
__slots__ = ()
|
||||
|
||||
|
||||
@classmethod
|
||||
def _from_iterable(cls, it):
|
||||
return SortedSet(it)
|
||||
|
||||
|
||||
def __getitem__(self, index):
|
||||
"""Lookup item at `index` in sorted items view.
|
||||
|
||||
``siv.__getitem__(index)`` <==> ``siv[index]``
|
||||
|
||||
Supports slicing.
|
||||
|
||||
Runtime complexity: `O(log(n))` -- approximate.
|
||||
|
||||
>>> sd = SortedDict({'a': 1, 'b': 2, 'c': 3})
|
||||
>>> siv = sd.items()
|
||||
>>> siv[0]
|
||||
('a', 1)
|
||||
>>> siv[-1]
|
||||
('c', 3)
|
||||
>>> siv[:]
|
||||
[('a', 1), ('b', 2), ('c', 3)]
|
||||
>>> siv[100]
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
IndexError: list index out of range
|
||||
|
||||
:param index: integer or slice for indexing
|
||||
:return: item or list of items
|
||||
:raises IndexError: if index out of range
|
||||
|
||||
"""
|
||||
_mapping = self._mapping
|
||||
_mapping_list = _mapping._list
|
||||
|
||||
if isinstance(index, slice):
|
||||
keys = _mapping_list[index]
|
||||
return [(key, _mapping[key]) for key in keys]
|
||||
|
||||
key = _mapping_list[index]
|
||||
return key, _mapping[key]
|
||||
|
||||
|
||||
__delitem__ = _view_delitem
|
||||
|
||||
|
||||
class SortedValuesView(ValuesView, Sequence):
|
||||
"""Sorted values view is a dynamic view of the sorted dict's values.
|
||||
|
||||
When the sorted dict's values change, the view reflects those changes.
|
||||
|
||||
The values view implements the sequence abstract base class.
|
||||
|
||||
"""
|
||||
__slots__ = ()
|
||||
|
||||
|
||||
def __getitem__(self, index):
|
||||
"""Lookup value at `index` in sorted values view.
|
||||
|
||||
``siv.__getitem__(index)`` <==> ``siv[index]``
|
||||
|
||||
Supports slicing.
|
||||
|
||||
Runtime complexity: `O(log(n))` -- approximate.
|
||||
|
||||
>>> sd = SortedDict({'a': 1, 'b': 2, 'c': 3})
|
||||
>>> svv = sd.values()
|
||||
>>> svv[0]
|
||||
1
|
||||
>>> svv[-1]
|
||||
3
|
||||
>>> svv[:]
|
||||
[1, 2, 3]
|
||||
>>> svv[100]
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
IndexError: list index out of range
|
||||
|
||||
:param index: integer or slice for indexing
|
||||
:return: value or list of values
|
||||
:raises IndexError: if index out of range
|
||||
|
||||
"""
|
||||
_mapping = self._mapping
|
||||
_mapping_list = _mapping._list
|
||||
|
||||
if isinstance(index, slice):
|
||||
keys = _mapping_list[index]
|
||||
return [_mapping[key] for key in keys]
|
||||
|
||||
key = _mapping_list[index]
|
||||
return _mapping[key]
|
||||
|
||||
|
||||
__delitem__ = _view_delitem
|
2646
lib/python3.13/site-packages/sortedcontainers/sortedlist.py
Normal file
2646
lib/python3.13/site-packages/sortedcontainers/sortedlist.py
Normal file
File diff suppressed because it is too large
Load Diff
733
lib/python3.13/site-packages/sortedcontainers/sortedset.py
Normal file
733
lib/python3.13/site-packages/sortedcontainers/sortedset.py
Normal file
@ -0,0 +1,733 @@
|
||||
"""Sorted Set
|
||||
=============
|
||||
|
||||
:doc:`Sorted Containers<index>` is an Apache2 licensed Python sorted
|
||||
collections library, written in pure-Python, and fast as C-extensions. The
|
||||
:doc:`introduction<introduction>` is the best way to get started.
|
||||
|
||||
Sorted set implementations:
|
||||
|
||||
.. currentmodule:: sortedcontainers
|
||||
|
||||
* :class:`SortedSet`
|
||||
|
||||
"""
|
||||
|
||||
from itertools import chain
|
||||
from operator import eq, ne, gt, ge, lt, le
|
||||
from textwrap import dedent
|
||||
|
||||
from .sortedlist import SortedList, recursive_repr
|
||||
|
||||
###############################################################################
|
||||
# BEGIN Python 2/3 Shims
|
||||
###############################################################################
|
||||
|
||||
try:
|
||||
from collections.abc import MutableSet, Sequence, Set
|
||||
except ImportError:
|
||||
from collections import MutableSet, Sequence, Set
|
||||
|
||||
###############################################################################
|
||||
# END Python 2/3 Shims
|
||||
###############################################################################
|
||||
|
||||
|
||||
class SortedSet(MutableSet, Sequence):
|
||||
"""Sorted set is a sorted mutable set.
|
||||
|
||||
Sorted set values are maintained in sorted order. The design of sorted set
|
||||
is simple: sorted set uses a set for set-operations and maintains a sorted
|
||||
list of values.
|
||||
|
||||
Sorted set values must be hashable and comparable. The hash and total
|
||||
ordering of values must not change while they are stored in the sorted set.
|
||||
|
||||
Mutable set methods:
|
||||
|
||||
* :func:`SortedSet.__contains__`
|
||||
* :func:`SortedSet.__iter__`
|
||||
* :func:`SortedSet.__len__`
|
||||
* :func:`SortedSet.add`
|
||||
* :func:`SortedSet.discard`
|
||||
|
||||
Sequence methods:
|
||||
|
||||
* :func:`SortedSet.__getitem__`
|
||||
* :func:`SortedSet.__delitem__`
|
||||
* :func:`SortedSet.__reversed__`
|
||||
|
||||
Methods for removing values:
|
||||
|
||||
* :func:`SortedSet.clear`
|
||||
* :func:`SortedSet.pop`
|
||||
* :func:`SortedSet.remove`
|
||||
|
||||
Set-operation methods:
|
||||
|
||||
* :func:`SortedSet.difference`
|
||||
* :func:`SortedSet.difference_update`
|
||||
* :func:`SortedSet.intersection`
|
||||
* :func:`SortedSet.intersection_update`
|
||||
* :func:`SortedSet.symmetric_difference`
|
||||
* :func:`SortedSet.symmetric_difference_update`
|
||||
* :func:`SortedSet.union`
|
||||
* :func:`SortedSet.update`
|
||||
|
||||
Methods for miscellany:
|
||||
|
||||
* :func:`SortedSet.copy`
|
||||
* :func:`SortedSet.count`
|
||||
* :func:`SortedSet.__repr__`
|
||||
* :func:`SortedSet._check`
|
||||
|
||||
Sorted list methods available:
|
||||
|
||||
* :func:`SortedList.bisect_left`
|
||||
* :func:`SortedList.bisect_right`
|
||||
* :func:`SortedList.index`
|
||||
* :func:`SortedList.irange`
|
||||
* :func:`SortedList.islice`
|
||||
* :func:`SortedList._reset`
|
||||
|
||||
Additional sorted list methods available, if key-function used:
|
||||
|
||||
* :func:`SortedKeyList.bisect_key_left`
|
||||
* :func:`SortedKeyList.bisect_key_right`
|
||||
* :func:`SortedKeyList.irange_key`
|
||||
|
||||
Sorted set comparisons use subset and superset relations. Two sorted sets
|
||||
are equal if and only if every element of each sorted set is contained in
|
||||
the other (each is a subset of the other). A sorted set is less than
|
||||
another sorted set if and only if the first sorted set is a proper subset
|
||||
of the second sorted set (is a subset, but is not equal). A sorted set is
|
||||
greater than another sorted set if and only if the first sorted set is a
|
||||
proper superset of the second sorted set (is a superset, but is not equal).
|
||||
|
||||
"""
|
||||
def __init__(self, iterable=None, key=None):
|
||||
"""Initialize sorted set instance.
|
||||
|
||||
Optional `iterable` argument provides an initial iterable of values to
|
||||
initialize the sorted set.
|
||||
|
||||
Optional `key` argument defines a callable that, like the `key`
|
||||
argument to Python's `sorted` function, extracts a comparison key from
|
||||
each value. The default, none, compares values directly.
|
||||
|
||||
Runtime complexity: `O(n*log(n))`
|
||||
|
||||
>>> ss = SortedSet([3, 1, 2, 5, 4])
|
||||
>>> ss
|
||||
SortedSet([1, 2, 3, 4, 5])
|
||||
>>> from operator import neg
|
||||
>>> ss = SortedSet([3, 1, 2, 5, 4], neg)
|
||||
>>> ss
|
||||
SortedSet([5, 4, 3, 2, 1], key=<built-in function neg>)
|
||||
|
||||
:param iterable: initial values (optional)
|
||||
:param key: function used to extract comparison key (optional)
|
||||
|
||||
"""
|
||||
self._key = key
|
||||
|
||||
# SortedSet._fromset calls SortedSet.__init__ after initializing the
|
||||
# _set attribute. So only create a new set if the _set attribute is not
|
||||
# already present.
|
||||
|
||||
if not hasattr(self, '_set'):
|
||||
self._set = set()
|
||||
|
||||
self._list = SortedList(self._set, key=key)
|
||||
|
||||
# Expose some set methods publicly.
|
||||
|
||||
_set = self._set
|
||||
self.isdisjoint = _set.isdisjoint
|
||||
self.issubset = _set.issubset
|
||||
self.issuperset = _set.issuperset
|
||||
|
||||
# Expose some sorted list methods publicly.
|
||||
|
||||
_list = self._list
|
||||
self.bisect_left = _list.bisect_left
|
||||
self.bisect = _list.bisect
|
||||
self.bisect_right = _list.bisect_right
|
||||
self.index = _list.index
|
||||
self.irange = _list.irange
|
||||
self.islice = _list.islice
|
||||
self._reset = _list._reset
|
||||
|
||||
if key is not None:
|
||||
self.bisect_key_left = _list.bisect_key_left
|
||||
self.bisect_key_right = _list.bisect_key_right
|
||||
self.bisect_key = _list.bisect_key
|
||||
self.irange_key = _list.irange_key
|
||||
|
||||
if iterable is not None:
|
||||
self._update(iterable)
|
||||
|
||||
|
||||
@classmethod
|
||||
def _fromset(cls, values, key=None):
|
||||
"""Initialize sorted set from existing set.
|
||||
|
||||
Used internally by set operations that return a new set.
|
||||
|
||||
"""
|
||||
sorted_set = object.__new__(cls)
|
||||
sorted_set._set = values
|
||||
sorted_set.__init__(key=key)
|
||||
return sorted_set
|
||||
|
||||
|
||||
@property
|
||||
def key(self):
|
||||
"""Function used to extract comparison key from values.
|
||||
|
||||
Sorted set compares values directly when the key function is none.
|
||||
|
||||
"""
|
||||
return self._key
|
||||
|
||||
|
||||
def __contains__(self, value):
|
||||
"""Return true if `value` is an element of the sorted set.
|
||||
|
||||
``ss.__contains__(value)`` <==> ``value in ss``
|
||||
|
||||
Runtime complexity: `O(1)`
|
||||
|
||||
>>> ss = SortedSet([1, 2, 3, 4, 5])
|
||||
>>> 3 in ss
|
||||
True
|
||||
|
||||
:param value: search for value in sorted set
|
||||
:return: true if `value` in sorted set
|
||||
|
||||
"""
|
||||
return value in self._set
|
||||
|
||||
|
||||
def __getitem__(self, index):
|
||||
"""Lookup value at `index` in sorted set.
|
||||
|
||||
``ss.__getitem__(index)`` <==> ``ss[index]``
|
||||
|
||||
Supports slicing.
|
||||
|
||||
Runtime complexity: `O(log(n))` -- approximate.
|
||||
|
||||
>>> ss = SortedSet('abcde')
|
||||
>>> ss[2]
|
||||
'c'
|
||||
>>> ss[-1]
|
||||
'e'
|
||||
>>> ss[2:5]
|
||||
['c', 'd', 'e']
|
||||
|
||||
:param index: integer or slice for indexing
|
||||
:return: value or list of values
|
||||
:raises IndexError: if index out of range
|
||||
|
||||
"""
|
||||
return self._list[index]
|
||||
|
||||
|
||||
def __delitem__(self, index):
|
||||
"""Remove value at `index` from sorted set.
|
||||
|
||||
``ss.__delitem__(index)`` <==> ``del ss[index]``
|
||||
|
||||
Supports slicing.
|
||||
|
||||
Runtime complexity: `O(log(n))` -- approximate.
|
||||
|
||||
>>> ss = SortedSet('abcde')
|
||||
>>> del ss[2]
|
||||
>>> ss
|
||||
SortedSet(['a', 'b', 'd', 'e'])
|
||||
>>> del ss[:2]
|
||||
>>> ss
|
||||
SortedSet(['d', 'e'])
|
||||
|
||||
:param index: integer or slice for indexing
|
||||
:raises IndexError: if index out of range
|
||||
|
||||
"""
|
||||
_set = self._set
|
||||
_list = self._list
|
||||
if isinstance(index, slice):
|
||||
values = _list[index]
|
||||
_set.difference_update(values)
|
||||
else:
|
||||
value = _list[index]
|
||||
_set.remove(value)
|
||||
del _list[index]
|
||||
|
||||
|
||||
def __make_cmp(set_op, symbol, doc):
|
||||
"Make comparator method."
|
||||
def comparer(self, other):
|
||||
"Compare method for sorted set and set."
|
||||
if isinstance(other, SortedSet):
|
||||
return set_op(self._set, other._set)
|
||||
elif isinstance(other, Set):
|
||||
return set_op(self._set, other)
|
||||
return NotImplemented
|
||||
|
||||
set_op_name = set_op.__name__
|
||||
comparer.__name__ = '__{0}__'.format(set_op_name)
|
||||
doc_str = """Return true if and only if sorted set is {0} `other`.
|
||||
|
||||
``ss.__{1}__(other)`` <==> ``ss {2} other``
|
||||
|
||||
Comparisons use subset and superset semantics as with sets.
|
||||
|
||||
Runtime complexity: `O(n)`
|
||||
|
||||
:param other: `other` set
|
||||
:return: true if sorted set is {0} `other`
|
||||
|
||||
"""
|
||||
comparer.__doc__ = dedent(doc_str.format(doc, set_op_name, symbol))
|
||||
return comparer
|
||||
|
||||
|
||||
__eq__ = __make_cmp(eq, '==', 'equal to')
|
||||
__ne__ = __make_cmp(ne, '!=', 'not equal to')
|
||||
__lt__ = __make_cmp(lt, '<', 'a proper subset of')
|
||||
__gt__ = __make_cmp(gt, '>', 'a proper superset of')
|
||||
__le__ = __make_cmp(le, '<=', 'a subset of')
|
||||
__ge__ = __make_cmp(ge, '>=', 'a superset of')
|
||||
__make_cmp = staticmethod(__make_cmp)
|
||||
|
||||
|
||||
def __len__(self):
|
||||
"""Return the size of the sorted set.
|
||||
|
||||
``ss.__len__()`` <==> ``len(ss)``
|
||||
|
||||
:return: size of sorted set
|
||||
|
||||
"""
|
||||
return len(self._set)
|
||||
|
||||
|
||||
def __iter__(self):
|
||||
"""Return an iterator over the sorted set.
|
||||
|
||||
``ss.__iter__()`` <==> ``iter(ss)``
|
||||
|
||||
Iterating the sorted set while adding or deleting values may raise a
|
||||
:exc:`RuntimeError` or fail to iterate over all values.
|
||||
|
||||
"""
|
||||
return iter(self._list)
|
||||
|
||||
|
||||
def __reversed__(self):
|
||||
"""Return a reverse iterator over the sorted set.
|
||||
|
||||
``ss.__reversed__()`` <==> ``reversed(ss)``
|
||||
|
||||
Iterating the sorted set while adding or deleting values may raise a
|
||||
:exc:`RuntimeError` or fail to iterate over all values.
|
||||
|
||||
"""
|
||||
return reversed(self._list)
|
||||
|
||||
|
||||
def add(self, value):
|
||||
"""Add `value` to sorted set.
|
||||
|
||||
Runtime complexity: `O(log(n))` -- approximate.
|
||||
|
||||
>>> ss = SortedSet()
|
||||
>>> ss.add(3)
|
||||
>>> ss.add(1)
|
||||
>>> ss.add(2)
|
||||
>>> ss
|
||||
SortedSet([1, 2, 3])
|
||||
|
||||
:param value: value to add to sorted set
|
||||
|
||||
"""
|
||||
_set = self._set
|
||||
if value not in _set:
|
||||
_set.add(value)
|
||||
self._list.add(value)
|
||||
|
||||
_add = add
|
||||
|
||||
|
||||
def clear(self):
|
||||
"""Remove all values from sorted set.
|
||||
|
||||
Runtime complexity: `O(n)`
|
||||
|
||||
"""
|
||||
self._set.clear()
|
||||
self._list.clear()
|
||||
|
||||
|
||||
def copy(self):
|
||||
"""Return a shallow copy of the sorted set.
|
||||
|
||||
Runtime complexity: `O(n)`
|
||||
|
||||
:return: new sorted set
|
||||
|
||||
"""
|
||||
return self._fromset(set(self._set), key=self._key)
|
||||
|
||||
__copy__ = copy
|
||||
|
||||
|
||||
def count(self, value):
|
||||
"""Return number of occurrences of `value` in the sorted set.
|
||||
|
||||
Runtime complexity: `O(1)`
|
||||
|
||||
>>> ss = SortedSet([1, 2, 3, 4, 5])
|
||||
>>> ss.count(3)
|
||||
1
|
||||
|
||||
:param value: value to count in sorted set
|
||||
:return: count
|
||||
|
||||
"""
|
||||
return 1 if value in self._set else 0
|
||||
|
||||
|
||||
def discard(self, value):
|
||||
"""Remove `value` from sorted set if it is a member.
|
||||
|
||||
If `value` is not a member, do nothing.
|
||||
|
||||
Runtime complexity: `O(log(n))` -- approximate.
|
||||
|
||||
>>> ss = SortedSet([1, 2, 3, 4, 5])
|
||||
>>> ss.discard(5)
|
||||
>>> ss.discard(0)
|
||||
>>> ss == set([1, 2, 3, 4])
|
||||
True
|
||||
|
||||
:param value: `value` to discard from sorted set
|
||||
|
||||
"""
|
||||
_set = self._set
|
||||
if value in _set:
|
||||
_set.remove(value)
|
||||
self._list.remove(value)
|
||||
|
||||
_discard = discard
|
||||
|
||||
|
||||
def pop(self, index=-1):
|
||||
"""Remove and return value at `index` in sorted set.
|
||||
|
||||
Raise :exc:`IndexError` if the sorted set is empty or index is out of
|
||||
range.
|
||||
|
||||
Negative indices are supported.
|
||||
|
||||
Runtime complexity: `O(log(n))` -- approximate.
|
||||
|
||||
>>> ss = SortedSet('abcde')
|
||||
>>> ss.pop()
|
||||
'e'
|
||||
>>> ss.pop(2)
|
||||
'c'
|
||||
>>> ss
|
||||
SortedSet(['a', 'b', 'd'])
|
||||
|
||||
:param int index: index of value (default -1)
|
||||
:return: value
|
||||
:raises IndexError: if index is out of range
|
||||
|
||||
"""
|
||||
# pylint: disable=arguments-differ
|
||||
value = self._list.pop(index)
|
||||
self._set.remove(value)
|
||||
return value
|
||||
|
||||
|
||||
def remove(self, value):
|
||||
"""Remove `value` from sorted set; `value` must be a member.
|
||||
|
||||
If `value` is not a member, raise :exc:`KeyError`.
|
||||
|
||||
Runtime complexity: `O(log(n))` -- approximate.
|
||||
|
||||
>>> ss = SortedSet([1, 2, 3, 4, 5])
|
||||
>>> ss.remove(5)
|
||||
>>> ss == set([1, 2, 3, 4])
|
||||
True
|
||||
>>> ss.remove(0)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
KeyError: 0
|
||||
|
||||
:param value: `value` to remove from sorted set
|
||||
:raises KeyError: if `value` is not in sorted set
|
||||
|
||||
"""
|
||||
self._set.remove(value)
|
||||
self._list.remove(value)
|
||||
|
||||
|
||||
def difference(self, *iterables):
|
||||
"""Return the difference of two or more sets as a new sorted set.
|
||||
|
||||
The `difference` method also corresponds to operator ``-``.
|
||||
|
||||
``ss.__sub__(iterable)`` <==> ``ss - iterable``
|
||||
|
||||
The difference is all values that are in this sorted set but not the
|
||||
other `iterables`.
|
||||
|
||||
>>> ss = SortedSet([1, 2, 3, 4, 5])
|
||||
>>> ss.difference([4, 5, 6, 7])
|
||||
SortedSet([1, 2, 3])
|
||||
|
||||
:param iterables: iterable arguments
|
||||
:return: new sorted set
|
||||
|
||||
"""
|
||||
diff = self._set.difference(*iterables)
|
||||
return self._fromset(diff, key=self._key)
|
||||
|
||||
__sub__ = difference
|
||||
|
||||
|
||||
def difference_update(self, *iterables):
|
||||
"""Remove all values of `iterables` from this sorted set.
|
||||
|
||||
The `difference_update` method also corresponds to operator ``-=``.
|
||||
|
||||
``ss.__isub__(iterable)`` <==> ``ss -= iterable``
|
||||
|
||||
>>> ss = SortedSet([1, 2, 3, 4, 5])
|
||||
>>> _ = ss.difference_update([4, 5, 6, 7])
|
||||
>>> ss
|
||||
SortedSet([1, 2, 3])
|
||||
|
||||
:param iterables: iterable arguments
|
||||
:return: itself
|
||||
|
||||
"""
|
||||
_set = self._set
|
||||
_list = self._list
|
||||
values = set(chain(*iterables))
|
||||
if (4 * len(values)) > len(_set):
|
||||
_set.difference_update(values)
|
||||
_list.clear()
|
||||
_list.update(_set)
|
||||
else:
|
||||
_discard = self._discard
|
||||
for value in values:
|
||||
_discard(value)
|
||||
return self
|
||||
|
||||
__isub__ = difference_update
|
||||
|
||||
|
||||
def intersection(self, *iterables):
|
||||
"""Return the intersection of two or more sets as a new sorted set.
|
||||
|
||||
The `intersection` method also corresponds to operator ``&``.
|
||||
|
||||
``ss.__and__(iterable)`` <==> ``ss & iterable``
|
||||
|
||||
The intersection is all values that are in this sorted set and each of
|
||||
the other `iterables`.
|
||||
|
||||
>>> ss = SortedSet([1, 2, 3, 4, 5])
|
||||
>>> ss.intersection([4, 5, 6, 7])
|
||||
SortedSet([4, 5])
|
||||
|
||||
:param iterables: iterable arguments
|
||||
:return: new sorted set
|
||||
|
||||
"""
|
||||
intersect = self._set.intersection(*iterables)
|
||||
return self._fromset(intersect, key=self._key)
|
||||
|
||||
__and__ = intersection
|
||||
__rand__ = __and__
|
||||
|
||||
|
||||
def intersection_update(self, *iterables):
|
||||
"""Update the sorted set with the intersection of `iterables`.
|
||||
|
||||
The `intersection_update` method also corresponds to operator ``&=``.
|
||||
|
||||
``ss.__iand__(iterable)`` <==> ``ss &= iterable``
|
||||
|
||||
Keep only values found in itself and all `iterables`.
|
||||
|
||||
>>> ss = SortedSet([1, 2, 3, 4, 5])
|
||||
>>> _ = ss.intersection_update([4, 5, 6, 7])
|
||||
>>> ss
|
||||
SortedSet([4, 5])
|
||||
|
||||
:param iterables: iterable arguments
|
||||
:return: itself
|
||||
|
||||
"""
|
||||
_set = self._set
|
||||
_list = self._list
|
||||
_set.intersection_update(*iterables)
|
||||
_list.clear()
|
||||
_list.update(_set)
|
||||
return self
|
||||
|
||||
__iand__ = intersection_update
|
||||
|
||||
|
||||
def symmetric_difference(self, other):
|
||||
"""Return the symmetric difference with `other` as a new sorted set.
|
||||
|
||||
The `symmetric_difference` method also corresponds to operator ``^``.
|
||||
|
||||
``ss.__xor__(other)`` <==> ``ss ^ other``
|
||||
|
||||
The symmetric difference is all values tha are in exactly one of the
|
||||
sets.
|
||||
|
||||
>>> ss = SortedSet([1, 2, 3, 4, 5])
|
||||
>>> ss.symmetric_difference([4, 5, 6, 7])
|
||||
SortedSet([1, 2, 3, 6, 7])
|
||||
|
||||
:param other: `other` iterable
|
||||
:return: new sorted set
|
||||
|
||||
"""
|
||||
diff = self._set.symmetric_difference(other)
|
||||
return self._fromset(diff, key=self._key)
|
||||
|
||||
__xor__ = symmetric_difference
|
||||
__rxor__ = __xor__
|
||||
|
||||
|
||||
def symmetric_difference_update(self, other):
|
||||
"""Update the sorted set with the symmetric difference with `other`.
|
||||
|
||||
The `symmetric_difference_update` method also corresponds to operator
|
||||
``^=``.
|
||||
|
||||
``ss.__ixor__(other)`` <==> ``ss ^= other``
|
||||
|
||||
Keep only values found in exactly one of itself and `other`.
|
||||
|
||||
>>> ss = SortedSet([1, 2, 3, 4, 5])
|
||||
>>> _ = ss.symmetric_difference_update([4, 5, 6, 7])
|
||||
>>> ss
|
||||
SortedSet([1, 2, 3, 6, 7])
|
||||
|
||||
:param other: `other` iterable
|
||||
:return: itself
|
||||
|
||||
"""
|
||||
_set = self._set
|
||||
_list = self._list
|
||||
_set.symmetric_difference_update(other)
|
||||
_list.clear()
|
||||
_list.update(_set)
|
||||
return self
|
||||
|
||||
__ixor__ = symmetric_difference_update
|
||||
|
||||
|
||||
def union(self, *iterables):
|
||||
"""Return new sorted set with values from itself and all `iterables`.
|
||||
|
||||
The `union` method also corresponds to operator ``|``.
|
||||
|
||||
``ss.__or__(iterable)`` <==> ``ss | iterable``
|
||||
|
||||
>>> ss = SortedSet([1, 2, 3, 4, 5])
|
||||
>>> ss.union([4, 5, 6, 7])
|
||||
SortedSet([1, 2, 3, 4, 5, 6, 7])
|
||||
|
||||
:param iterables: iterable arguments
|
||||
:return: new sorted set
|
||||
|
||||
"""
|
||||
return self.__class__(chain(iter(self), *iterables), key=self._key)
|
||||
|
||||
__or__ = union
|
||||
__ror__ = __or__
|
||||
|
||||
|
||||
def update(self, *iterables):
|
||||
"""Update the sorted set adding values from all `iterables`.
|
||||
|
||||
The `update` method also corresponds to operator ``|=``.
|
||||
|
||||
``ss.__ior__(iterable)`` <==> ``ss |= iterable``
|
||||
|
||||
>>> ss = SortedSet([1, 2, 3, 4, 5])
|
||||
>>> _ = ss.update([4, 5, 6, 7])
|
||||
>>> ss
|
||||
SortedSet([1, 2, 3, 4, 5, 6, 7])
|
||||
|
||||
:param iterables: iterable arguments
|
||||
:return: itself
|
||||
|
||||
"""
|
||||
_set = self._set
|
||||
_list = self._list
|
||||
values = set(chain(*iterables))
|
||||
if (4 * len(values)) > len(_set):
|
||||
_list = self._list
|
||||
_set.update(values)
|
||||
_list.clear()
|
||||
_list.update(_set)
|
||||
else:
|
||||
_add = self._add
|
||||
for value in values:
|
||||
_add(value)
|
||||
return self
|
||||
|
||||
__ior__ = update
|
||||
_update = update
|
||||
|
||||
|
||||
def __reduce__(self):
|
||||
"""Support for pickle.
|
||||
|
||||
The tricks played with exposing methods in :func:`SortedSet.__init__`
|
||||
confuse pickle so customize the reducer.
|
||||
|
||||
"""
|
||||
return (type(self), (self._set, self._key))
|
||||
|
||||
|
||||
@recursive_repr()
|
||||
def __repr__(self):
|
||||
"""Return string representation of sorted set.
|
||||
|
||||
``ss.__repr__()`` <==> ``repr(ss)``
|
||||
|
||||
:return: string representation
|
||||
|
||||
"""
|
||||
_key = self._key
|
||||
key = '' if _key is None else ', key={0!r}'.format(_key)
|
||||
type_name = type(self).__name__
|
||||
return '{0}({1!r}{2})'.format(type_name, list(self), key)
|
||||
|
||||
|
||||
def _check(self):
|
||||
"""Check invariants of sorted set.
|
||||
|
||||
Runtime complexity: `O(n)`
|
||||
|
||||
"""
|
||||
_set = self._set
|
||||
_list = self._list
|
||||
_list._check()
|
||||
assert len(_set) == len(_list)
|
||||
assert all(value in _set for value in _list)
|
Reference in New Issue
Block a user