def test_index(self): numbers = SortedList([1, 3, 4, 24, 6, 7, 23]) self.assertEqual(numbers.index(1), 0) self.assertEqual(numbers.index(3), 1) self.assertEqual(numbers.index(23), 5) self.assertEqual(numbers.index(4, stop=3), 2) self.assertEqual(numbers.index(4, stop=20), 2) self.assertEqual(numbers.index(23, start=4), 5) with self.assertRaises(ValueError): numbers.index(4, stop=2) with self.assertRaises(ValueError): numbers.index(23, stop=4) with self.assertRaises(ValueError): numbers.index(4, start=4)
class SortedDict(MutableMapping): """ A SortedDict provides the same methods as a dict. Additionally, a SortedDict efficiently maintains its keys in sorted order. Consequently, the keys method will return the keys in sorted order, the popitem method will remove the item with the highest key, etc. """ def __init__(self, *args, **kwargs): if len(args) > 0 and type(args[0]) == int: load = args[0] args = args[1:] else: load = 1000 self._dict = dict() self._list = SortedList(load=load) self.iloc = _IlocWrapper(self) self.update(*args, **kwargs) def clear(self): self._dict.clear() self._list.clear() def __contains__(self, key): return key in self._dict def __delitem__(self, key): del self._dict[key] self._list.remove(key) def __getitem__(self, key): return self._dict[key] def __eq__(self, that): return (len(self._dict) == len(that) and all((key in that) and (self[key] == that[key]) for key in self)) def __ne__(self, that): return (len(self._dict) != len(that) or any((key not in that) or (self[key] != that[key]) for key in self)) def __iter__(self): return iter(self._list) def __reversed__(self): return reversed(self._list) def __len__(self): return len(self._dict) def __setitem__(self, key, value): _dict = self._dict if key not in _dict: self._list.add(key) _dict[key] = value def copy(self): return SortedDict(self._list._load, self._dict) def __copy__(self): return self.copy() @classmethod def fromkeys(cls, seq, value=None): that = SortedDict((key, value) for key in seq) return that def get(self, key, default=None): return self._dict.get(key, default) def has_key(self, key): return key in self._dict def items(self): return list(self.iteritems()) def iteritems(self): _dict = self._dict return iter((key, _dict[key]) for key in self._list) def keys(self): return SortedSet(self._dict) def iterkeys(self): return iter(self._list) def values(self): return list(self.itervalues()) def itervalues(self): _dict = self._dict return iter(_dict[key] for key in self._list) def pop(self, key, default=_NotGiven): if key in self._dict: self._list.remove(key) return self._dict.pop(key) else: if default == _NotGiven: raise KeyError else: return default def popitem(self): _dict, _list = self._dict, self._list if len(_dict) == 0: raise KeyError key = _list.pop() value = _dict[key] del _dict[key] return (key, value) def setdefault(self, key, default=None): _dict = self._dict if key in _dict: return _dict[key] else: _dict[key] = default self._list.add(key) return default def update(self, *args, **kwargs): _dict, _list = self._dict, self._list if len(_dict) == 0: _dict.update(*args, **kwargs) _list.update(_dict) return if (len(kwargs) == 0 and len(args) == 1 and isinstance(args[0], dict)): pairs = args[0] else: pairs = dict(*args, **kwargs) if (10 * len(pairs)) > len(self._dict): self._dict.update(pairs) _list = self._list _list.clear() _list.update(self._dict) else: for key in pairs: self[key] = pairs[key] def index(self, key, start=None, stop=None): return self._list.index(key, start, stop) def bisect_left(self, key): return self._list.bisect_left(key) def bisect(self, key): return self._list.bisect(key) def bisect_right(self, key): return self._list.bisect_right(key) @not26 def viewkeys(self): return KeysView(self) @not26 def viewvalues(self): return ValuesView(self) @not26 def viewitems(self): return ItemsView(self) @recursive_repr def __repr__(self): _dict = self._dict return '%s({%s})' % ( self.__class__.__name__, ', '.join('%r: %r' % (key, _dict[key]) for key in self._list))
class SortedDict(MutableMapping): """ A SortedDict provides the same methods as a dict. Additionally, a SortedDict efficiently maintains its keys in sorted order. Consequently, the keys method will return the keys in sorted order, the popitem method will remove the item with the highest key, etc. """ def __init__(self, *args, **kwargs): if len(args) > 0 and type(args[0]) == int: load = args[0] args = args[1:] else: load = 1000 self._dict = dict() self._list = SortedList(load=load) self.iloc = _IlocWrapper(self) self.update(*args, **kwargs) def clear(self): self._dict.clear() self._list.clear() def __contains__(self, key): return key in self._dict def __delitem__(self, key): del self._dict[key] self._list.remove(key) def __getitem__(self, key): return self._dict[key] def __eq__(self, that): return (len(self._dict) == len(that) and all( (key in that) and (self[key] == that[key]) for key in self)) def __ne__(self, that): return (len(self._dict) != len(that) or any( (key not in that) or (self[key] != that[key]) for key in self)) def __iter__(self): return iter(self._list) def __reversed__(self): return reversed(self._list) def __len__(self): return len(self._dict) def __setitem__(self, key, value): _dict = self._dict if key not in _dict: self._list.add(key) _dict[key] = value def copy(self): return SortedDict(self._list._load, self._dict) def __copy__(self): return self.copy() @classmethod def fromkeys(cls, seq, value=None): that = SortedDict((key, value) for key in seq) return that def get(self, key, default=None): return self._dict.get(key, default) def has_key(self, key): return key in self._dict def items(self): return list(self.iteritems()) def iteritems(self): _dict = self._dict return iter((key, _dict[key]) for key in self._list) def keys(self): return SortedSet(self._dict) def iterkeys(self): return iter(self._list) def values(self): return list(self.itervalues()) def itervalues(self): _dict = self._dict return iter(_dict[key] for key in self._list) def pop(self, key, default=_NotGiven): if key in self._dict: self._list.remove(key) return self._dict.pop(key) else: if default == _NotGiven: raise KeyError else: return default def popitem(self): _dict, _list = self._dict, self._list if len(_dict) == 0: raise KeyError key = _list.pop() value = _dict[key] del _dict[key] return (key, value) def setdefault(self, key, default=None): _dict = self._dict if key in _dict: return _dict[key] else: _dict[key] = default self._list.add(key) return default def update(self, *args, **kwargs): _dict, _list = self._dict, self._list if len(_dict) == 0: _dict.update(*args, **kwargs) _list.update(_dict) return if (len(kwargs) == 0 and len(args) == 1 and isinstance(args[0], dict)): pairs = args[0] else: pairs = dict(*args, **kwargs) if (10 * len(pairs)) > len(self._dict): self._dict.update(pairs) _list = self._list _list.clear() _list.update(self._dict) else: for key in pairs: self[key] = pairs[key] def index(self, key, start=None, stop=None): return self._list.index(key, start, stop) def bisect_left(self, key): return self._list.bisect_left(key) def bisect(self, key): return self._list.bisect(key) def bisect_right(self, key): return self._list.bisect_right(key) @not26 def viewkeys(self): return KeysView(self) @not26 def viewvalues(self): return ValuesView(self) @not26 def viewitems(self): return ItemsView(self) @recursive_repr def __repr__(self): _dict = self._dict return '%s({%s})' % (self.__class__.__name__, ', '.join( '%r: %r' % (key, _dict[key]) for key in self._list))
class SortedSet(MutableSet, Sequence): """ A `SortedSet` provides the same methods as a `set`. Additionally, a `SortedSet` maintains its items in sorted order, allowing the `SortedSet` to be indexed. Unlike a `set`, a `SortedSet` requires items be hashable and comparable. """ def __init__(self, iterable=None, load=1000, _set=None): if _set is None: self._set = set() else: self._set = set self._list = SortedList(self._set, load=load) if iterable is not None: self.update(iterable) def __contains__(self, value): return (value in self._set) def __getitem__(self, index): if isinstance(index, slice): return SortedSet(self._list[index]) else: return self._list[index] def __delitem__(self, index): _list = self._list if isinstance(index, slice): values = _list[index] self._set.difference_update(values) else: value = _list[index] self._set.remove(value) del _list[index] def __setitem__(self, index, value): _list, _set = self._list, self._set prev = _list[index] _list[index] = value if isinstance(index, slice): _set.difference_update(prev) _set.update(prev) else: _set.remove(prev) _set.add(prev) def __eq__(self, that): if len(self) != len(that): return False if isinstance(that, SortedSet): return (self._list == that._list) elif isinstance(that, set): return (self._set == that) else: _set = self._set return all(val in _set for val in that) def __ne__(self, that): if len(self) != len(that): return True if isinstance(that, SortedSet): return (self._list != that._list) elif isinstance(that, set): return (self._set != that) else: _set = self._set return any(val not in _set for val in that) def __lt__(self, that): if isinstance(that, set): return (self._set < that) else: return (len(self) < len(that)) and all(val in that for val in self._list) def __gt__(self, that): if isinstance(that, set): return (self._set > that) else: _set = self._set return (len(self) > len(that)) and all(val in _set for val in that) def __le__(self, that): if isinstance(that, set): return (self._set <= that) else: return all(val in that for val in self._list) def __ge__(self, that): if isinstance(that, set): return (self._set >= that) else: _set = self._set return all(val in _set for val in that) def __and__(self, that): return self.intersection(that) def __or__(self, that): return self.union(that) def __sub__(self, that): return self.difference(that) def __xor__(self, that): return self.symmetric_difference(that) def __iter__(self): return iter(self._list) def __len__(self): return len(self._set) def __reversed__(self): return reversed(self._list) def add(self, value): if value not in self._set: self._set.add(value) self._list.add(value) def bisect_left(self, value): return self._list.bisect_left(value) def bisect(self, value): return self._list.bisect(value) def bisect_right(self, value): return self._list.bisect_right(value) def clear(self): self._set.clear() self._list.clear() def copy(self): return SortedSet(load=self._list._load, _set=set(self._set)) def __copy__(self): return self.copy() def count(self, value): return int(value in self._set) def discard(self, value): if value in self._set: self._set.remove(value) self._list.discard(value) def index(self, value, start=None, stop=None): return self._list.index(value, start, stop) def isdisjoint(self, that): return self._set.isdisjoint(that) def issubset(self, that): return self._set.issubset(that) def issuperset(self, that): return self._set.issuperset(that) def pop(self, index=-1): value = self._list.pop(index) self._set.remove(value) return value def remove(self, value): self._set.remove(value) self._list.remove(value) def difference(self, *iterables): diff = self._set.difference(*iterables) new_set = SortedSet(load=self._list._load, _set=diff) return new_set def difference_update(self, *iterables): values = set(chain(*iterables)) if (4 * len(values)) > len(self): self._set.difference_update(values) self._list.clear() self._list.update(self._set) else: _discard = self.discard for value in values: _discard(value) def intersection(self, *iterables): comb = self._set.intersection(*iterables) new_set = SortedSet(load=self._list._load, _set=comb) return new_set def intersection_update(self, *iterables): self._set.intersection_update(*iterables) self._list.clear() self._list.update(self._set) def symmetric_difference(self, that): diff = self._set.symmetric_difference(that) new_set = SortedSet(load=self._list._load, _set=diff) return new_set def symmetric_difference_update(self, that): self._set.symmetric_difference_update(that) self._list.clear() self._list.update(self._set) def union(self, *iterables): return SortedSet(chain(iter(self), *iterables), load=self._list._load) def update(self, *iterables): values = set(chain(*iterables)) if (4 * len(values)) > len(self): self._set.update(values) self._list.clear() self._list.update(self._set) else: _add = self.add for value in values: _add(value) @recursive_repr def __repr__(self): return '%s(%r)' % (self.__class__.__name__, list(self))