ordered_set.py 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. # http://code.activestate.com/recipes/576694/
  2. import collections.abc
  3. class OrderedSet(collections.abc.MutableSet):
  4. def __init__(self, iterable=None):
  5. self.end = end = []
  6. end += [None, end, end] # sentinel node for doubly linked list
  7. self.map = {} # key --> [key, prev, next]
  8. if iterable is not None:
  9. self |= iterable
  10. def __len__(self):
  11. return len(self.map)
  12. def __contains__(self, key):
  13. return key in self.map
  14. def update(self, other):
  15. for i in other:
  16. self.add(i)
  17. def add(self, key):
  18. if key not in self.map:
  19. end = self.end
  20. curr = end[1]
  21. curr[2] = end[1] = self.map[key] = [key, curr, end]
  22. def discard(self, key):
  23. if key in self.map:
  24. key, prev, next = self.map.pop(key)
  25. prev[2] = next
  26. next[1] = prev
  27. def __iter__(self):
  28. end = self.end
  29. curr = end[2]
  30. while curr is not end:
  31. yield curr[0]
  32. curr = curr[2]
  33. def __reversed__(self):
  34. end = self.end
  35. curr = end[1]
  36. while curr is not end:
  37. yield curr[0]
  38. curr = curr[1]
  39. def pop(self, last=True):
  40. if not self:
  41. raise KeyError('set is empty')
  42. key = self.end[1][0] if last else self.end[2][0]
  43. self.discard(key)
  44. return key
  45. def __repr__(self):
  46. if not self:
  47. return '%s()' % (self.__class__.__name__,)
  48. return '%s(%r)' % (self.__class__.__name__, list(self))
  49. def __eq__(self, other):
  50. if isinstance(other, OrderedSet):
  51. return len(self) == len(other) and list(self) == list(other)
  52. return set(self) == set(other)
  53. if __name__ == '__main__':
  54. s = OrderedSet('abracadaba')
  55. t = OrderedSet('simsalabim')
  56. print((s | t))
  57. print((s & t))
  58. print((s - t))