CMS 3D CMS Logo

OrderedSet.py
Go to the documentation of this file.
1 from __future__ import print_function
2 # The MIT License (MIT)
3 #
4 # Copyright (c) 19 March 2009 Created by Raymond Hettinger (MIT)
5 #
6 # Permission is hereby granted, free of charge, to any person obtaining a copy
7 # of this software and associated documentation files (the "Software"), to deal
8 # in the Software without restriction, including without limitation the rights
9 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 # copies of the Software, and to permit persons to whom the Software is
11 # furnished to do so, subject to the following conditions:
12 #
13 # The above copyright notice and this permission notice shall be included in
14 # all copies or substantial portions of the Software.
15 #
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 # DEALINGS IN THE SOFTWARE.
23 #
24 # Copied from URL http://code.activestate.com/recipes/576694-orderedset/
25 # on 15 November 2016
26 
27 import collections.abc
28 
29 class OrderedSet(collections.abc.MutableSet):
30 
31  def __init__(self, iterable=None):
32  self.end = end = []
33  end += [None, end, end] # sentinel node for doubly linked list
34  self.map = {} # key --> [key, prev, next]
35  if iterable is not None:
36  self |= iterable
37 
38  def __len__(self):
39  return len(self.map)
40 
41  def __contains__(self, key):
42  return key in self.map
43 
44  def add(self, key):
45  if key not in self.map:
46  end = self.end
47  curr = end[1]
48  curr[2] = end[1] = self.map[key] = [key, curr, end]
49 
50  def discard(self, key):
51  if key in self.map:
52  key, prev, next = self.map.pop(key)
53  prev[2] = next
54  next[1] = prev
55 
56  def __iter__(self):
57  end = self.end
58  curr = end[2]
59  while curr is not end:
60  yield curr[0]
61  curr = curr[2]
62 
63  def __reversed__(self):
64  end = self.end
65  curr = end[1]
66  while curr is not end:
67  yield curr[0]
68  curr = curr[1]
69 
70  def pop(self, last=True):
71  if not self:
72  raise KeyError('set is empty')
73  key = self.end[1][0] if last else self.end[2][0]
74  self.discard(key)
75  return key
76 
77  def __repr__(self):
78  if not self:
79  return '%s()' % (self.__class__.__name__,)
80  return '%s(%r)' % (self.__class__.__name__, list(self))
81 
82  def __eq__(self, other):
83  if isinstance(other, OrderedSet):
84  return len(self) == len(other) and list(self) == list(other)
85  return set(self) == set(other)
86 
87 
88 if __name__ == '__main__':
89  import unittest
90  class TestModuleCommand(unittest.TestCase):
91  def setUp(self):
92  """Nothing to do """
93  pass
94  def testSetOperations(self):
95  s = OrderedSet('abracadaba')
96  t = OrderedSet('simsalabim')
97  self.assertEqual(str((s | t)), "OrderedSet(['a', 'b', 'r', 'c', 'd', 's', 'i', 'm', 'l'])")
98  self.assertEqual(str((s & t)), "OrderedSet(['a', 'b'])")
99  self.assertEqual(str(s - t),"OrderedSet(['r', 'c', 'd'])")
100  unittest.main()
def __init__(self, iterable=None)
Definition: OrderedSet.py:31
def __eq__(self, other)
Definition: OrderedSet.py:82
def add(self, key)
Definition: OrderedSet.py:44
def discard(self, key)
Definition: OrderedSet.py:50
def __contains__(self, key)
Definition: OrderedSet.py:41
def __reversed__(self)
Definition: OrderedSet.py:63
#define str(s)
def pop(self, last=True)
Definition: OrderedSet.py:70