00001 ## 00002 # 00003 # This module implements a class Set using lists. Using lists 00004 # allows the Set class to be general, but it can be inefficient 00005 # for sets with large numbers of elements. If you need speed, 00006 # consider using the setf.py implementation, which uses dictionaries 00007 # to store set elements. It's fast, but the tradeoff is that 00008 # you can only store hashable objects, which appear to me to be 00009 # numbers and strings. 00010 # 00011 # Both set.py and setf.py have the identical set of class methods 00012 # and attributes. 00013 # 00014 # The class is named Set in both cases. If you import the class with 00015 # a statement like 'import Set from set', you can change to the 00016 # other implementation by just changing it to 'import Set from setf'. 00017 # 00018 # Copyright (C) 2002 GDS Software 00019 # 00020 # This program is free software; you can redistribute it and/or 00021 # modify it under the terms of the GNU General Public License as 00022 # published by the Free Software Foundation; either version 2 of 00023 # the License, or (at your option) any later version. 00024 # 00025 # This program is distributed in the hope that it will be useful, 00026 # but WITHOUT ANY WARRANTY; without even the implied warranty of 00027 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00028 # GNU General Public License for more details. 00029 # 00030 # You should have received a copy of the GNU General Public 00031 # License along with this program; if not, write to the Free 00032 # Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, 00033 # MA 02111-1307 USA 00034 # 00035 # See http://www.gnu.org/licenses/licenses.html for more details. 00036 # 00037 00038 __version__ = "$Id: set.py,v 1.3 2002/08/21 12:41:49 donp Exp $" 00039 00040 ## 00041 # Class that implements a set. The supported methods are: 00042 # 00043 # add_to_set(element) 00044 # Adds the element to the set. Element can be a list, tuple, 00045 # dictionary, string, number, or set. If it is a list, tuple, 00046 # dictionary, or set and self.decompose is true, it is broken 00047 # into its component parts and those are stored in the set 00048 # (otherwise element is just added to the set). 00049 # delete_from_set(element) 00050 # Deletes the element from the set. Element can be a list, 00051 # tuple, dictionary, string, number, or a set. If it is a 00052 # list, tuple, dictionary, or set and self.decompose is true, 00053 # element is broken into its component parts and each part is 00054 # deleted from the set. An exception will occur if one of 00055 # the elements is not in the set and self.harsh is true. 00056 # intersection(other_set) 00057 # Returns a set that is the intersection of self and other_set. 00058 # union(other_set) 00059 # Returns a set that is the union of self and other_set. 00060 # difference(other_set) 00061 # Returns a set that consists of all elements in self that are 00062 # not in other_set. 00063 # is_in_set(element) 00064 # Returns 1 if element is in the set, 0 if not. 00065 # is_empty_set() 00066 # Returns 1 if the set is empty. 00067 # is_subset_of(other_set) 00068 # Returns 1 if self is a subset of other_set; otherwise returns 0. 00069 # is_proper_subset_of(other_set) 00070 # Returns 1 if self is a proper subset of other_set; otherwise 00071 # returns 0. 00072 # list() 00073 # Returns a list of the elements of the set. 00074 # __len__() 00075 # Returns the number of elements in the set. 00076 # __getitem__(element) 00077 # Returns 1 if element is in set, 0 if not. 00078 # __and__(other_set) 00079 # __mul__(other_set) 00080 # __rmul__(other_set) 00081 # Same as intersection method. 00082 # __or__(other_set) 00083 # __add__(other_set) 00084 # __radd__(other_set) 00085 # Same as union method. 00086 # __repr__ 00087 # Returns a string representation of the set. 00088 # __sub__ 00089 # Same as difference() method. 00090 # __cmp__(other_set) 00091 # Returns 0 if self and other_set have the same member elements, 00092 # otherwise returns 1. 00093 # __repr__() 00094 # Returns a string representation of the Set object. 00095 # 00096 # Because of the supported methods, you may use sets in the following 00097 # ways; assumes r, s, and t are set objects: 00098 # 00099 # t = r + s Union 00100 # t = r | s Union 00101 # t = r * s Intersection 00102 # t = r & s Intersection 00103 # t = r - s Difference 00104 # r == s Equality 00105 # r != s Non-equality 00106 # s["a"] Returns 1 if the string "a" is in set. 00107 # 00108 # You can pass in a dictionary, list, or tuple and it will be 00109 # converted to a set. If you pass in a dictionary, the keys are 00110 # the set elements (the values are ignored). 00111 # 00112 # Attributes & parameters: 00113 # 00114 # sorted Set to true to sort the set before printing or 00115 # returning as a list. Default is false. 00116 # 00117 # harsh If true, causes an exception to be thrown if you 00118 # try to delete an element not in the list. Defaults 00119 # to true. 00120 # 00121 # decompose (Parameter to constructor) Set this to true 00122 # if you want the value parameter decomposed into 00123 # its components and those components then make 00124 # up the set. If the decompose parameter is false, 00125 # the value parameter becomes the one and only 00126 # element of the set. Default is true. 00127 # 00128 # version The class version string (it's maintained with 00129 # RCS). 00130 # 00131 # 00132 class Set: 00133 00134 def __init__(self, value=None, decompose=1, harsh=1, sorted=0): 00135 self.set = [] 00136 self.sorted = sorted 00137 self.harsh = harsh 00138 self.decompose = decompose 00139 self.version = "$Id: set.py,v 1.3 2002/08/21 12:41:49 donp Exp $" 00140 if value != None: 00141 if (type(value) == type([]) or type(value) == type(()) or type(value) == type({}) or type(value) == type(self)) and decompose: 00142 if type(value) == type({}): 00143 set_list = value.keys() 00144 elif type(value) == type(()): 00145 set_list = list(value) 00146 elif type(value) == type(self): 00147 set_list = value.list() 00148 else: 00149 set_list = value 00150 self.set = set_list 00151 else: 00152 self.set.append(value) 00153 00154 def add_to_set(self, object): 00155 if (type(object) == type([]) or type(object) == type(()) or type(object) == type({}) or type(object) == type(self)) and self.decompose: 00156 if type(object) == type({}): 00157 set_list = object.keys() 00158 elif type(object) == type(()): 00159 set_list = list(object) 00160 elif type(object) == type(self): 00161 set_list = object.list() 00162 else: 00163 set_list = object 00164 self.set = self.set + set_list 00165 else: 00166 self.set.append(object) 00167 00168 def delete_from_set(self, object): 00169 items_to_delete = [] 00170 if (type(object) == type([]) or type(object) == type(()) or type(object) == type({}) or type(object) == type(self)) and self.decompose: 00171 if type(object) == type({}): 00172 items_to_delete = object.keys() 00173 elif type(object) == type(()): 00174 items_to_delete = list(object) 00175 elif type(object) == type(self): 00176 items_to_delete = object.list() 00177 else: 00178 items_to_delete = object 00179 else: 00180 items_to_delete = [object] 00181 for item in items_to_delete: 00182 if item in self.set: 00183 ix = self.set.index(item) 00184 del self.set[ix] 00185 else: 00186 if self.harsh: 00187 raise "Error", "item '%s' not in set" % `item` 00188 00189 def intersection(self, other_set): 00190 self.__check_if_is_a_set(other_set) 00191 new_set = [] 00192 if len(self.set) > len(other_set.set): 00193 iter_set = self.set[:] 00194 smaller_set = other_set.set 00195 else: 00196 iter_set = other_set.set[:] 00197 smaller_set = self.set 00198 for element in iter_set: 00199 if element in smaller_set: 00200 new_set.append(element) 00201 return Set(new_set, decompose=1) 00202 00203 def union(self, other_set): 00204 self.__check_if_is_a_set(other_set) 00205 if len(self.set) > len(other_set.set): 00206 new_set = self.set[:] 00207 iter_set = self.set[:] 00208 smaller_set = other_set.set 00209 else: 00210 new_set = other_set.set[:] 00211 iter_set = other_set.set[:] 00212 smaller_set = self.set 00213 for element in smaller_set: 00214 if element not in iter_set: 00215 new_set.append(element) 00216 return Set(new_set, decompose=1) 00217 00218 ## 00219 # Returns a set that consists of all elements in self that are 00220 # not in other_set. 00221 # 00222 def difference(self, other_set): 00223 self.__check_if_is_a_set(other_set) 00224 new_set = self.set[:] 00225 for element in other_set.set: 00226 try: 00227 ix = new_set.index(element) 00228 del new_set[ix] 00229 except: 00230 pass 00231 return Set(new_set, decompose=1) 00232 00233 def is_in_set(self, element): 00234 return self.__getitem__(element) 00235 00236 def is_empty_set(self): 00237 return not len(self.set) 00238 00239 ## 00240 # Return 1 if self is a subset of other_set, otherwise 00241 # return 0. This is based on the theorem that if A is a 00242 # subset of B, then (A union B) = B and (A intersection B) = A. 00243 # Here, we get the intersection of self and other_set and see 00244 # if it is equal to other_set. 00245 # 00246 def is_subset_of(self, other_set): 00247 self.__check_if_is_a_set(other_set) 00248 return self.__cmp__(self.intersection(other_set)) == 0 00249 00250 ## 00251 # Return 1 if self is a proper subset of other_set, otherwise 00252 # return 0. 00253 # 00254 def is_proper_subset_of(self, other_set): 00255 return self.is_subset_of(other_set) and (len(self.set) != len(other_set.set)) 00256 00257 def list(self): 00258 s = self.set[:] 00259 if self.sorted: 00260 s.sort() 00261 return s 00262 00263 def __check_if_is_a_set(self, other_set): 00264 if type(other_set) != type(self): 00265 raise "Error", "other_set must be a set object" 00266 00267 def __len__(self): 00268 return len(self.set) 00269 00270 ## 00271 # If element is in set, return 1; otherwise return 0. 00272 # 00273 def __getitem__(self, element): 00274 try: 00275 ix = self.set.index(element) 00276 return 1 00277 except: 00278 return 0 00279 00280 def __and__(self, other_set): 00281 return self.intersection(other_set) 00282 00283 def __mul__(self, other_set): 00284 return self.intersection(other_set) 00285 00286 def __rmul__(self, other_set): 00287 return self.intersection(other_set) 00288 00289 def __or__(self, other_set): 00290 return self.union(other_set) 00291 00292 def __add__(self, other_set): 00293 return self.union(other_set) 00294 00295 def __radd__(self, other_set): 00296 return self.union(other_set) 00297 00298 def __sub__(self, other_set): 00299 return self.difference(other_set) 00300 00301 ## 00302 # Returns 0 if self.set is equal to other; otherwise returns 1. 00303 # 00304 def __cmp__(self, other_set): 00305 if type(other_set) != type(self) or len(other_set.set) != len(self.set): 00306 return 1 00307 for element in other_set.set: 00308 if element not in other_set.set: 00309 return 1 00310 return 0 00311 00312 def __repr__(self): 00313 s = self.set[:] 00314 if self.sorted: 00315 s.sort() 00316 str = `s` 00317 str = "<" + str[1:] 00318 return str[:-1] + ">" 00319 00320 if __name__ == "__main__": 00321 # Test the Set class 00322 from testset import Test 00323 Test(N=5, use_list_implementation=1) 00324 00325
© Copyright 2008-2009 Vyper Logix Corp., All Right Reserved; If you reference this document or any part of this document you must use the citation verbatim (including the link) "© Copyright 2008-2009 Vyper Logix Corp., All Right Reserved."
Notice: This source code contained in this document is NOT open source and is NOT being distributed as open source.
122,241 lines of code and growing...