orderedset.py 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. # -*- coding: utf-8 -*-
  2. # OrderedSet
  3. # Copyright (c) 2009 Raymond Hettinger
  4. #
  5. # Permission is hereby granted, free of charge, to any person
  6. # obtaining a copy of this software and associated documentation files
  7. # (the "Software"), to deal in the Software without restriction,
  8. # including without limitation the rights to use, copy, modify, merge,
  9. # publish, distribute, sublicense, and/or sell copies of the Software,
  10. # and to permit persons to whom the Software is furnished to do so,
  11. # subject to the following conditions:
  12. #
  13. # The above copyright notice and this permission notice shall be
  14. # included in all copies or substantial portions of the Software.
  15. #
  16. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  17. # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  18. # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  19. # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  20. # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  21. # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  22. # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  23. # OTHER DEALINGS IN THE SOFTWARE.
  24. from marshmallow.compat import MutableSet
  25. class OrderedSet(MutableSet):
  26. def __init__(self, iterable=None):
  27. self.end = end = []
  28. end += [None, end, end] # sentinel node for doubly linked list
  29. self.map = {} # key --> [key, prev, next]
  30. if iterable is not None:
  31. self |= iterable
  32. def __len__(self):
  33. return len(self.map)
  34. def __contains__(self, key):
  35. return key in self.map
  36. def add(self, key):
  37. if key not in self.map:
  38. end = self.end
  39. curr = end[1]
  40. curr[2] = end[1] = self.map[key] = [key, curr, end]
  41. def discard(self, key):
  42. if key in self.map:
  43. key, prev, next = self.map.pop(key)
  44. prev[2] = next
  45. next[1] = prev
  46. def __iter__(self):
  47. end = self.end
  48. curr = end[2]
  49. while curr is not end:
  50. yield curr[0]
  51. curr = curr[2]
  52. def __reversed__(self):
  53. end = self.end
  54. curr = end[1]
  55. while curr is not end:
  56. yield curr[0]
  57. curr = curr[1]
  58. def pop(self, last=True):
  59. if not self:
  60. raise KeyError('set is empty')
  61. key = self.end[1][0] if last else self.end[2][0]
  62. self.discard(key)
  63. return key
  64. def __repr__(self):
  65. if not self:
  66. return '%s()' % (self.__class__.__name__,)
  67. return '%s(%r)' % (self.__class__.__name__, list(self))
  68. def __eq__(self, other):
  69. if isinstance(other, OrderedSet):
  70. return len(self) == len(other) and list(self) == list(other)
  71. return set(self) == set(other)
  72. if __name__ == '__main__':
  73. s = OrderedSet('abracadaba')
  74. t = OrderedSet('simsalabim')
  75. print(s | t)
  76. print(s & t)
  77. print(s - t)