sortedcontainers - SortedSet、SortedDict

SortedSet和SortedDict是sortedcontainers的另外两种有序容器。其内部实现都是建立在SortedList的基础上实现的。使用SortedList来保证其有序性,使用set或继承dict来实现其set或dict特性。

SortedDict

class SortedDict(dict):
    def __init__(self, *args, **kwargs):

        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)  # 使用Sortedlist保持其有序性

        _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)

    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})
        """
        dict.__delitem__(self, key)  # 先删除dict里的再删除SortedList中的
        self._list_remove(key)

    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:  # 如果是新添加,先添加到SortedList中
            self._list_add(key)
        dict.__setitem__(self, key, value)

使用

  """
    Mutable mapping methods:

  * :func:`SortedDict.__getitem__` (inherited from dict)
  * :func:`SortedDict.__setitem__`
  * :func:`SortedDict.__delitem__`
  * :func:`SortedDict.__iter__`
  * :func:`SortedDict.__len__` (inherited from dict)
  """
  # 继承自dict所以可以使用dict的常用方法

SortedSet

SortedSet通过set和SortedList实现。

class SortedSet:
    def __init__(self, iterable=None, key=None):
 
        self._key = key
        if not hasattr(self, '_set'):
            self._set = set()  # 使用内置set

        self._list = SortedList(self._set, key=key)  # 使用一个SortedList保证有序性

        # 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)

    def __contains__(self, value):
        """直接使用内部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']
        """
        # 通过内部的SortedList来获取置顶坐标的值
        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'])
        """
        # 通过index删除内容
        # 先删内部set中的内容再删内部SortedList
        _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 __len__(self):
        """返回的是内部set长度
        """
        return len(self._set)


    def __iter__(self):
        """Return an iterator over the sorted set.
        返回的是内部Sortedlist的迭代器
        """
        return iter(self._list)


    def __reversed__(self):
        """Return a reverse iterator over the sorted set.
        ``ss.__reversed__()`` <==> ``reversed(ss)``

        """
        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
        # 先做判断是否在内部set中,不在同时添加到内部set和内部SortedList
        if value not in _set:
            _set.add(value)
            self._list.add(value)

    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)


    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)

使用

"""
    Mutable set methods:

    * :func:`SortedSet.__contains__`
    * :func:`SortedSet.__iter__`
    * :func:`SortedSet.__len__`
    * :func:`SortedSet.add`
    * :func:`SortedSet.discard`
"""

copy方法是浅拷贝

    @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

    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)

posted @ 2022-08-02 00:02  店里最会撒谎白玉汤  阅读(447)  评论(0)    收藏  举报