def test_remove(self): sl = SortedList() sl.insert(1) sl.remove(1) sl.remove(1) self.assertIsNone(sl.head) self.assertIsNone(sl.tail)
def test_remove(self): sl = SortedList() sl.insert( 1 ) sl.remove( 1 ) sl.remove( 1 ) self.assertIsNone(sl.head) self.assertIsNone(sl.tail)
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_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_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_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_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_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 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
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_insert_first(self): sl = SortedList() sl.insert(1) self.assertEqual(sl.head.data, 1) self.assertEqual(sl.tail.data, 1)
def test_insert_first(self): sl = SortedList() sl.insert( 1 ) self.assertEqual(sl.head.data, 1) self.assertEqual(sl.tail.data, 1)