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)
Example #2
0
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))
Example #3
0
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))
Example #4
0
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))
Example #5
0
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))