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)