Skip to content

Instantly share code, notes, and snippets.

@jcmgray
Created May 30, 2020 07:19
Show Gist options
  • Save jcmgray/866290fc3c76ba39211dc0ef72ffd900 to your computer and use it in GitHub Desktop.
Save jcmgray/866290fc3c76ba39211dc0ef72ffd900 to your computer and use it in GitHub Desktop.
oset - an fast ordered set implemenation using the 'orderedness' of py3.6+ dicts
class oset:
"""An ordered set which stores elements as the keys of a dict (ordered as
of python 3.6). 'A few times' slower than using a set directly for small
sizes, but makes everything deterministic.
"""
def __init__(self, it):
self._d = dict.fromkeys(it)
@classmethod
def _from_dict(cls, d):
obj = object.__new__(oset)
obj._d = d
return obj
@classmethod
def from_dict(cls, d):
"""Public method makes sure to copy incoming dictionary.
"""
return oset._from_dict(d.copy())
def copy(self):
return oset.from_dict(self._d)
def add(self, k):
self._d[k] = None
def discard(self, k):
self._d.pop(k, None)
def remove(self, k):
self._d.pop(k)
def clear(self):
self._d.clear()
def update(self, *others):
for o in others:
self._d.update(o._d)
def union(self, *others):
u = self.copy()
u.update(*others)
return u
def intersection_update(self, *others):
if len(others) > 1:
si = set.intersection(*(set(o._d) for o in others))
else:
si = others[0]._d
self._d = {k: None for k in self._d if k in si}
def intersection(self, *others):
if len(others) > 1:
si = set.intersection(*(set(o._d) for o in others))
else:
si = others[0]._d
return oset._from_dict({k: None for k in self._d if k in si})
def difference_update(self, *others):
if len(others) > 1:
su = set.union(*(set(o._d) for o in others))
else:
su = others[0]._d
self._d = {k: None for k in self._d if k not in su}
def difference(self, *others):
if len(others) > 1:
su = set.union(*(set(o._d) for o in others))
else:
su = others[0]._d
return oset._from_dict({k: None for k in self._d if k not in su})
def __or__(self, other):
return self.union(other)
def __ior__(self, other):
self.update(other)
return self
def __and__(self, other):
return self.intersection(other)
def __iand__(self, other):
self.intersection_update(other)
return self
def __sub__(self, other):
return self.difference(other)
def __isub__(self, other):
self.difference_update(other)
return self
def __len__(self):
return self._d.__len__()
def __iter__(self):
return self._d.__iter__()
def __contains__(self, x):
return self._d.__contains__(x)
def __repr__(self):
return f"oset({list(self._d)})"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment