def test_remove(self): sl = SortedList() sl.insert( 1 ) sl.remove( 1 ) sl.remove( 1 ) self.assertIsNone(sl.head) self.assertIsNone(sl.tail)
def __init__( self ): win = StandardWindow("Testing", "Elementary Sorted Table") win.callback_delete_request_add(lambda o: elm.exit()) titles = [] for i in range(COLUMNS): titles.append( ("Column " + str(i), True if i != 2 else False) ) slist = SortedList(win, titles=titles, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) for i in range(ROWS): row = [] for j in range(COLUMNS): data = random.randint(0, ROWS*COLUMNS) row.append(data) slist.row_pack(row, sort=False) #slist.sort_by_column(1) slist.show() win.resize_object_add(slist) win.resize(600, 400) win.show()
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 test_stress(self): sl = SortedList() items = list( range(3000) ) shuffle( items ) for i in range(3000): sl.insert( items[i] ) sl.remove( i / 2 ) sl.remove( i / 3 )
def test_insert_second_1(self): sl = SortedList() sl.insert( 1 ) sl.insert( 2 ) self.assertEqual(sl.head.data, 1) self.assertEqual(sl.head.next.data, 2) self.assertEqual(sl.tail.data, 2) self.assertIsNone(sl.tail.next)
def test_insert_second_1(self): sl = SortedList() sl.insert(1) sl.insert(2) self.assertEqual(sl.head.data, 1) self.assertEqual(sl.head.next.data, 2) self.assertEqual(sl.tail.data, 2) self.assertIsNone(sl.tail.next)
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 test_remove_last(self): sl = SortedList() sl.insert( 2 ) sl.insert( 1 ) sl.remove( 2 ) self.assertEqual(sl.head.data, 1) self.assertEqual(sl.tail.data, 1) self.assertIsNone(sl.tail.next)
def test_containment(self): numbers = SortedList([1, 3, 4, 24, 6, 7, 23]) self.assertTrue(1 in numbers) self.assertFalse(2 in numbers) self.assertTrue(3 in numbers) self.assertFalse(5 in numbers) self.assertTrue(23 in numbers) self.assertTrue(4 in numbers) self.assertFalse(21 in numbers)
def test_remove_middle(self): sl = SortedList() sl.insert(3) sl.insert(2) sl.insert(1) sl.remove(2) self.assertEqual(sl.head.data, 1) self.assertEqual(sl.head.next.data, 3) self.assertEqual(sl.tail.data, 3) self.assertIsNone(sl.tail.next)
def __init__(self, iterable=None, key=lambda val: val, value_orderable=True, load=1000): self._key = key self._list = SortedList(load=load) self._ordered = value_orderable if value_orderable: self._pair = lambda key, value: (key, value) else: self._pair = Pair if iterable is not None: self.update(iterable)
def test_remove(self): sl = SortedList() sl.insert(1) sl.remove(1) sl.remove(1) self.assertIsNone(sl.head) self.assertIsNone(sl.tail)
def __init__(self): win = StandardWindow("Testing", "Elementary Sorted Table") win.callback_delete_request_add(lambda o: elm.exit()) titles = [] for i in range(COLUMNS): titles.append(("Column " + str(i), True if i != 2 else False)) slist = SortedList(win, titles=titles, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) for i in range(ROWS): row = [] for j in range(COLUMNS): data = random.randint(0, ROWS * COLUMNS) row.append(data) slist.row_pack(row, sort=False) #slist.sort_by_column(1) slist.show() win.resize_object_add(slist) win.resize(600, 400) win.show()
def test_stress(self): sl = SortedList() items = list(range(3000)) shuffle(items) for i in range(3000): sl.insert(items[i]) sl.remove(i / 2) sl.remove(i / 3)
def test_remove_first(self): sl = SortedList() sl.insert(2) sl.insert(1) sl.remove(1) self.assertEqual(sl.head.data, 2) self.assertEqual(sl.tail.data, 2) self.assertIsNone(sl.tail.next)
def test_unordered_setting_and_inserting_not_allowed(self): numbers = SortedList([1, 3, 4, 24, 6, 7, 23]) self.assertEqual(numbers[1], 3) with self.assertRaises(Exception): numbers[1] = 8 with self.assertRaises(Exception): numbers.insert(0, 8) with self.assertRaises(Exception): numbers.append(8) self.assertEqual(numbers[0], 1) self.assertEqual(numbers[1], 3) self.assertEqual(numbers[-1], 24) self.assertEqual(len(numbers), 7)
def test_key_function(self): words = SortedList(['apple', 'lime', 'Lemon'], key=str.lower) self.assertEqual(list(words), ['apple', 'Lemon', 'lime']) words.add('Banana') self.assertEqual(list(words), ['apple', 'Banana', 'Lemon', 'lime']) self.assertNotIn('banana', words) self.assertIn('Banana', words) self.assertEqual(words.find('banana'), -1) self.assertEqual(words.find('Banana'), 1) words.remove('Lemon') self.assertEqual(list(words), ['apple', 'Banana', 'lime']) words.add('pear') self.assertEqual(list(words), ['apple', 'Banana', 'lime', 'pear']) self.assertEqual(words.find('LIME'), -1) self.assertEqual(words.find('lime'), 2) self.assertEqual(words.rfind('LIME'), -1) self.assertEqual(words.rfind('lime'), 2) self.assertEqual(words.count('LIME'), 0) self.assertEqual(words.count('lime'), 1) words.add('LIME') self.assertEqual(words.count('lime'), 1) self.assertEqual(words.count('LIME'), 1) words.add('lime') self.assertEqual(words.count('lime'), 2) self.assertEqual(words.count('LIME'), 1)
def test_indexing(self): numbers = SortedList([1, 3, 4, 24, 6, 7, 23]) self.assertEqual(numbers[1], 3) self.assertEqual(numbers[-1], 24)
def test_time_efficiency(self): sorted_list = SortedList(MANY_BIG_NUMBERS) unsorted_list = sorted(MANY_BIG_NUMBERS) with Timer() as sorted_add: sorted_list.add(0) sorted_list.add(20000) sorted_list.add(49000) sorted_list.add(49999) with Timer() as unsorted_add: unsorted_list.insert(unsorted_list.index(0), 0) unsorted_list.insert(unsorted_list.index(20000), 20000) unsorted_list.insert(unsorted_list.index(49000), 49000) unsorted_list.insert(unsorted_list.index(49999), 49999) self.assertLess(sorted_add.elapsed, unsorted_add.elapsed) with Timer() as sorted_count: self.assertEqual(sorted_list.count(1), 1) self.assertEqual(sorted_list.count(25000), 1) self.assertEqual(sorted_list.count(49000), 2) self.assertEqual(sorted_list.count(50000), 0) with Timer() as unsorted_count: self.assertEqual(unsorted_list.count(1), 1) self.assertEqual(unsorted_list.count(25000), 1) self.assertEqual(unsorted_list.count(49000), 2) self.assertEqual(unsorted_list.count(50000), 0) self.assertLess(sorted_count.elapsed, unsorted_count.elapsed) with Timer() as sorted_contains: self.assertTrue(0 in sorted_list) self.assertTrue(25000 in sorted_list) self.assertFalse(30000.5 in sorted_list) self.assertFalse(100000 in sorted_list) self.assertFalse(-1 in sorted_list) self.assertTrue(48000 in sorted_list) with Timer() as unsorted_contains: self.assertTrue(0 in unsorted_list) self.assertTrue(25000 in unsorted_list) self.assertFalse(30000.5 in unsorted_list) self.assertFalse(100000 in unsorted_list) self.assertFalse(-1 in unsorted_list) self.assertTrue(48000 in unsorted_list) self.assertLess(sorted_contains.elapsed, unsorted_contains.elapsed)
def test_length(self): numbers = SortedList([1, 3, 4, 24, 6, 7, 23]) self.assertEqual(len(numbers), 7)
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)
def test_insert_first(self): sl = SortedList() sl.insert(1) self.assertEqual(sl.head.data, 1) self.assertEqual(sl.tail.data, 1)
def test_initializer_copies_input(self): input_numbers = [1, 3, 4, 24, 6, 7, 23] numbers = SortedList(input_numbers) input_numbers.append(100) self.assertEqual(list(numbers), [1, 3, 4, 6, 7, 23, 24]) self.assertEqual(list(numbers), list(numbers))
def test_sorted_add(self): numbers = SortedList([1, 3, 4, 24, 6, 7, 23]) numbers.add(26) self.assertEqual(list(numbers), [1, 3, 4, 6, 7, 23, 24, 26]) numbers.add(2) self.assertEqual(list(numbers), [1, 2, 3, 4, 6, 7, 23, 24, 26])
def test_insert_first(self): sl = SortedList() sl.insert( 1 ) self.assertEqual(sl.head.data, 1) self.assertEqual(sl.tail.data, 1)
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 SortedListWithKey(MutableSequence): def __init__(self, iterable=None, key=lambda val: val, value_orderable=True, load=1000): self._key = key self._list = SortedList(load=load) self._ordered = value_orderable if value_orderable: self._pair = lambda key, value: (key, value) else: self._pair = Pair if iterable is not None: self.update(iterable) def clear(self): self._list.clear() def add(self, value): pair = self._pair(self._key(value), value) self._list.add(pair) def update(self, iterable): _key, _pair = self._key, self._pair self._list.update(_pair(_key(val), val) for val in iterable) def __contains__(self, value): _list = self._list _key = self._key(value) _pair = self._pair(_key, value) if self._ordered: return _pair in _list _maxes = _list._maxes if _maxes is None: return False pos = bisect_left(_maxes, _pair) if pos == len(_maxes): return False _lists = _list._lists idx = bisect_left(_lists[pos], _pair) len_lists = len(_lists) len_sublist = len(_lists[pos]) while True: pair = _lists[pos][idx] if _key != pair.key: return False if value == pair.value: return True idx += 1 if idx == len_sublist: pos += 1 if pos == len_lists: return False len_sublist = len(_lists[pos]) idx = 0 def discard(self, value): _list = self._list _key = self._key(value) _pair = self._pair(_key, value) if self._ordered: _list.discard(_pair) return _maxes = _list._maxes if _maxes is None: return pos = bisect_left(_maxes, _pair) if pos == len(_maxes): return _lists = _list._lists idx = bisect_left(_lists[pos], _pair) len_lists = len(_lists) len_sublist = len(_lists[pos]) while True: pair = _lists[pos][idx] if _key != pair.key: return if value == pair.value: _list._delete(pos, idx) return idx += 1 if idx == len_sublist: pos += 1 if pos == len_lists: return len_sublist = len(_lists[pos]) idx = 0 def remove(self, value): _list = self._list _key = self._key(value) _pair = self._pair(_key, value) if self._ordered: _list.remove(_pair) return _maxes = _list._maxes if _maxes is None: raise ValueError pos = bisect_left(_maxes, _pair) if pos == len(_maxes): raise ValueError _lists = _list._lists idx = bisect_left(_lists[pos], _pair) len_lists = len(_lists) len_sublist = len(_lists[pos]) while True: pair = _lists[pos][idx] if _key != pair.key: raise ValueError if value == pair.value: _list._delete(pos, idx) return idx += 1 if idx == len_sublist: pos += 1 if pos == len_lists: raise ValueError len_sublist = len(_lists[pos]) idx = 0 def __delitem__(self, index): del self._list[index] def __getitem__(self, index): if isinstance(index, slice): return list(tup[1] for tup in self._list[index]) else: return self._list[index][1] def __setitem__(self, index, value): _key, _pair = self._key, self._pair if isinstance(index, slice): self._list[index] = list(_pair(_key(val), val) for val in value) else: self._list[index] = _pair(_key(value), value) def __iter__(self): return iter(tup[1] for tup in iter(self._list)) def __reversed__(self): return iter(tup[1] for tup in reversed(self._list)) def __len__(self): return len(self._list) def bisect_left(self, value): pair = self._pair(self._key(value), value) return self._list.bisect_left(pair) def bisect(self, value): pair = self._pair(self._key(value), value) return self._list.bisect(pair) def bisect_right(self, value): pair = self._pair(self._key(value), value) return self._list.bisect_right(pair) def count(self, value): _list = self._list _key = self._key(value) _pair = self._pair(_key, value) if self._ordered: return _list.count(_pair) _maxes = _list._maxes if _maxes is None: return 0 pos = bisect_left(_maxes, _pair) if pos == len(_maxes): return 0 _lists = _list._lists idx = bisect_left(_lists[pos], _pair) total = 0 len_lists = len(_lists) len_sublist = len(_lists[pos]) while True: pair = _lists[pos][idx] if _key != pair.key: return total if value == pair.value: total += 1 idx += 1 if idx == len_sublist: pos += 1 if pos == len_lists: return total len_sublist = len(_lists[pos]) idx = 0 def copy(self): _key, _ordered, _load = self._key, self._ordered, self._list._load kwargs = dict(key=_key, value_orderable=_ordered, load=_load) return SortedListWithKey(self, **kwargs) def __copy__(self): return self.copy() def append(self, value): pair = self._pair(self._key(value), value) self._list.append(pair) def extend(self, iterable): _key, _pair = self._key, self._pair self._list.extend(_pair(_key(val), val) for val in iterable) def insert(self, index, value): pair = self._pair(self._key(value), value) self._list.insert(index, pair) def pop(self, index=-1): return self._list.pop(index)[1] def index(self, value, start=None, stop=None): _list = self._list _key = self._key(value) _pair = self._pair(_key, value) if self._ordered: return _list.index(_pair, start, stop) _len = _list._len if start == None: start = 0 if start < 0: start += _len if start < 0: start = 0 if stop == None: stop = _len if stop < 0: stop += _len if stop > _len: stop = _len if stop <= start: raise ValueError _maxes = _list._maxes pos = bisect_left(_maxes, _pair) if pos == len(_maxes): raise ValueError _lists = _list._lists idx = bisect_left(_lists[pos], _pair) len_lists = len(_lists) len_sublist = len(_lists[pos]) while True: pair = _lists[pos][idx] if _key != pair.key: raise ValueError if value == pair.value: loc = _list._loc(pos, idx) if start <= loc < stop: return loc idx += 1 if idx == len_sublist: pos += 1 if pos == len_lists: raise ValueError len_sublist = len(_lists[pos]) idx = 0 def as_list(self): return list(tup[1] for tup in self._list.as_list()) def __add__(self, that): result = SortedListWithKey( key=self._key, value_orderable=self._ordered, load=self._list._load) values = self.as_list() values.extend(that) result.update(values) return result def __iadd__(self, that): self.update(that) return self def __mul__(self, that): values = self.as_list() * that return SortedListWithKey( values, key=self._key, value_orderable=self._ordered, load=self._list._load) def __imul__(self, that): values = self.as_list() * that self.clear() self.update(values) return self def __eq__(self, that): return ((len(self) == len(that)) and all(lhs == rhs for lhs, rhs in zip(self, that))) def __ne__(self, that): return ((len(self) != len(that)) or any(lhs != rhs for lhs, rhs in zip(self, that))) def __lt__(self, that): return ((len(self) <= len(that)) and all(lhs < rhs for lhs, rhs in zip(self, that))) def __le__(self, that): return ((len(self) <= len(that)) and all(lhs <= rhs for lhs, rhs in zip(self, that))) def __gt__(self, that): return ((len(self) >= len(that)) and all(lhs > rhs for lhs, rhs in zip(self, that))) def __ge__(self, that): return ((len(self) >= len(that)) and all(lhs >= rhs for lhs, rhs in zip(self, that))) @recursive_repr def __repr__(self): return '%s(%s, key=%r, value_orderable=%r, load=%r)' % ( self.__class__.__name__, self.as_list(), self._key, self._ordered, self._list._load)
def test_sorting_strings(self): words = SortedList(['apple', 'lime', 'Lemon']) words.add('Banana') self.assertEqual(list(words), ['Banana', 'Lemon', 'apple', 'lime'])
def test_init_SL(self): sl = SortedList() self.assertIsNone(sl.head) self.assertIsNone(sl.tail)
def test_string_representation(self): numbers = SortedList([1, 3, 4, 24, 6, 7, 23]) self.assertEqual(repr(numbers), "SortedList([1, 3, 4, 6, 7, 23, 24])") self.assertEqual(str(numbers), repr(numbers))
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))
def test_sorted_remove(self): numbers = SortedList([1, 3, 4, 24, 6, 7, 23]) numbers.remove(3) self.assertEqual(list(numbers), [1, 4, 6, 7, 23, 24]) with self.assertRaises(ValueError): numbers.remove(2)
def test_sorted_initializer_and_iteration(self): numbers = SortedList([1, 3, 4, 24, 6, 7, 23]) self.assertEqual(list(numbers), [1, 3, 4, 6, 7, 23, 24]) self.assertEqual(list(numbers), list(numbers))
def setUp(self): self.sorted_list = SortedList()
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))
def test_find_rfind_and_count(self): numbers = SortedList([2, 11, 2, 1, 29, 3, 7, 4, 2, 18, 4, 2]) self.assertEqual(numbers.find(1), 0) self.assertEqual(numbers.find(2), 1) self.assertEqual(numbers.find(3), 5) self.assertEqual(numbers.find(4), 6) self.assertEqual(numbers.find(5), -1) self.assertEqual(numbers.find(7), 8) self.assertEqual(numbers.find(100), -1) self.assertEqual(numbers.find(0), -1) self.assertEqual(numbers.count(1), 1) self.assertEqual(numbers.count(2), 4) self.assertEqual(numbers.count(3), 1) self.assertEqual(numbers.count(4), 2) self.assertEqual(numbers.count(5), 0) self.assertEqual(numbers.count(6), 0) self.assertEqual(numbers.count(7), 1) self.assertEqual(numbers.rfind(1), 0) self.assertEqual(numbers.rfind(2), 4) self.assertEqual(numbers.rfind(3), 5) self.assertEqual(numbers.rfind(4), 7) self.assertEqual(numbers.rfind(5), -1) self.assertEqual(numbers.rfind(7), 8) self.assertEqual(numbers.rfind(100), -1) self.assertEqual(numbers.rfind(0), -1)
class SortedListTestCase(unittest.TestCase): def setUp(self): self.sorted_list = SortedList() @property def is_sorted(self): for i, item in enumerate(self.sorted_list): if i == 0: current = item else: if current > item: return False return True def test_append_is_sorted(self): items = [] for _ in xrange(200): num = random.uniform(-100, 100) self.sorted_list.append(num) self.assertTrue(self.is_sorted) def test_append_keeps_items(self): items = [] for _ in xrange(200): num = random.uniform(-100, 100) self.sorted_list.append(num) items.append(num) items.sort() for i, j in zip(items, self.sorted_list): self.assertEqual(i, j) def test_extend_is_sorted(self): nums = range(-100, 100) random.shuffle(nums) self.sorted_list.extend(nums) self.assertTrue(self.is_sorted) def test_extend_keeps_items(self): nums = range(-100, 100) random.shuffle(nums) self.sorted_list.extend(nums) nums.sort() for i, j in zip(nums, self.sorted_list): self.assertEqual(i, j) def test_setitem_is_sorted(self): nums = xrange(-100, 100) self.sorted_list.extend(nums) for _ in xrange(200): self.sorted_list[random.randint(0, len(self.sorted_list) - 1)] = random.uniform(-100, 100) self.assertTrue(self.is_sorted) def test_setitem_keeps_items(self): nums = range(-100, 100) self.sorted_list.extend(nums) for _ in xrange(200): index = random.randint(0, len(self.sorted_list) - 1) num = random.uniform(-100, 100) self.sorted_list[index] = num nums[index] = num nums.sort() for i, j in zip(self.sorted_list, nums): self.assertEqual(i, j)
def compare(source_records: iter, target_records: iter, *, max_mismatch_size): source_mismatch_records = SortedList() target_mismatch_records = SortedList() fetch_source = fetch_target = True source_record = target_record = None source_found = target_found = False while True: if fetch_source: try: source_record = next(source_records) source_found = False except StopIteration: if not target_found: if not source_mismatch_records.remove(target_record): target_mismatch_records.insert(target_record) check_remaining(source_records, source_mismatch_records, target_records, target_mismatch_records) break if fetch_target: try: target_record = next(target_records) target_found = False except StopIteration: if not source_found: if not target_mismatch_records.remove(source_record): source_mismatch_records.insert(source_record) check_remaining(source_records, source_mismatch_records, target_records, target_mismatch_records) break if source_record == target_record: source_found = target_found = fetch_source = fetch_target = True else: fetch_source = source_found = target_mismatch_records.remove( source_record) fetch_target = target_found = source_mismatch_records.remove( target_record) if not fetch_source and not fetch_target: fetch_source = fetch_target = True source_mismatch_records.insert(source_record) target_mismatch_records.insert(target_record) if (len(source_mismatch_records) >= max_mismatch_size or len(target_mismatch_records) >= max_mismatch_size): return source_mismatch_records, target_mismatch_records return source_mismatch_records, target_mismatch_records