def test_hash_table_removes_correctly(self): ht = HashTable(0x10) ht.put("key-0", "val-0") ht.put("key-1", "val-1") ht.put("key-2", "val-2") return_value = ht.get("key-0") self.assertTrue(return_value == "val-0") return_value = ht.get("key-1") self.assertTrue(return_value == "val-1") return_value = ht.get("key-2") self.assertTrue(return_value == "val-2") ht.delete("key-2") ht.delete("key-1") ht.delete("key-0") return_value = ht.get("key-0") self.assertTrue(return_value is None) return_value = ht.get("key-1") self.assertTrue(return_value is None) return_value = ht.get("key-2") self.assertTrue(return_value is None)
def test_hash_table_resize(self): ht = HashTable(8) ht.put("key-0", "val-0") ht.put("key-1", "val-1") ht.put("key-2", "val-2") ht.put("key-3", "val-3") ht.put("key-4", "val-4") ht.put("key-5", "val-5") ht.put("key-6", "val-6") ht.put("key-7", "val-7") ht.put("key-8", "val-8") ht.put("key-9", "val-9") self.assertTrue(len(ht.storage) == 16) return_value = ht.get("key-0") self.assertTrue(return_value == "val-0") return_value = ht.get("key-1") self.assertTrue(return_value == "val-1") return_value = ht.get("key-2") self.assertTrue(return_value == "val-2") return_value = ht.get("key-3") self.assertTrue(return_value == "val-3") return_value = ht.get("key-4") self.assertTrue(return_value == "val-4") return_value = ht.get("key-5") self.assertTrue(return_value == "val-5") return_value = ht.get("key-6") self.assertTrue(return_value == "val-6") return_value = ht.get("key-7") self.assertTrue(return_value == "val-7") return_value = ht.get("key-8") self.assertTrue(return_value == "val-8") return_value = ht.get("key-9") self.assertTrue(return_value == "val-9") ht.delete("key-0") ht.delete("key-1") ht.delete("key-2") ht.delete("key-3") ht.delete("key-4") ht.delete("key-5") ht.delete("key-6") ht.delete("key-7") self.assertTrue(len(ht.storage) == 8)
def test_delete(self): ht = HashTable() ht.set('I', 1) ht.set('V', 5) ht.set('X', 10) assert ht.length() == 3 ht.delete('I') ht.delete('X') assert ht.length() == 1 with self.assertRaises(KeyError): ht.delete('X') with self.assertRaises(KeyError): ht.delete('A')
def test_delete(self): ht = HashTable() ht.set('I', 1) ht.set('V', 5) ht.set('X', 10) assert ht.length() == 3 ht.delete('I') ht.delete('X') assert ht.length() == 1 with self.assertRaises(KeyError): ht.delete('X') # Key no longer exists with self.assertRaises(KeyError): ht.delete('A') # Key does not exist
def test_delete(self): ht = HashTable() ht.set('I', 1) ht.set('V', 5) ht.set('X', 10) print("This is the hash table:", ht.items()) assert ht.length() == 3 ht.delete('I') ht.delete('X') assert ht.length() == 1 with self.assertRaises(KeyError): ht.delete('X') # Key no longer exists with self.assertRaises(KeyError): ht.delete('A') # Key does not exist
print("ENTRIES:") print(table.entries) table.put("Zandalorian", "Z") table.put("Xorolydian", "X") table.put("Hyrulian", "H") table.put("Partypartian", "P") print("ENTRIES:") print(table.entries) print(table.get("Zandalorian")) print(table.get("Dorian")) print(table.get("Locrian")) table.delete("Zandalorian") table.delete("Xorolydian") table.delete("Hyrulian") table.delete("Partypartian") print("ENTRIES:") print(table.entries) print(table.get("Partypartian")) print(table.get("Hyrulian")) print(table.get("Xorolydian")) print(table.get("Zandalorian")) table.delete("Zandalorian") table.delete("Xorolydian") table.delete("Hyrulian")
class Set(object): def __init__(self, elements=None): self.size = 0 if elements is None: self.data = HashTable(4) else: self.data = HashTable(len(elements)) def contains(self, element): """return a boolean indicating whether element is in this set""" contain = self.data.contains(element) return contain def add(self, element): """add element to this set, if not present already""" if element not in self.data.keys(): self.data.set(element, None) self.size += 1 else: raise ValueError("Element already exists in set") def remove(self, element): """remove element from this set, if present, or else raise KeyError""" if element in self.data.keys(): self.data.delete(element) self.size -= 1 else: raise KeyError("Element not in set") def union(self, other_set): """return a new set that is the union of this set and other_set""" new_set = Set(self.data.keys()) for element in other_set.data.keys(): if self.data.contains(element): continue else: new_set.add(element) return new_set def intersection(self, other_set): """return a new set that is the intersection of this set and other_set""" if other_set.data and self.data is not None: new_set = Set() for element in other_set.data.keys(): if self.data.contains(element): new_set.add(element) return new_set else: return ValueError("Set is empty") def difference(self, other_set): """return a new set that is the difference of this set and other_set""" if other_set and self.data is not None: new_set = Set() for element in self.data.keys(): if other_set.keys().contains(element): self.data.remove(element) new_set = self.data.keys return new_set def is_subset(self, other_set): """return a boolean indicating whether other_set is a subset of this set""" if other_set and self.data is not None: for element in other_set.data.keys(): if self.data.keys().contains(element): continue else: return False return True
class Set(): def __init__(self, elements=None): """Initialized this Set with the given data.""" self.items = HashTable() self.size = 0 if elements is not None: for item in elements: self.add(item) def length(self): """Calculates the length of the set.""" return self.items.length() def contains(self, element): """Checks if the element is in the set.""" return self.items.contains(element) def add(self, element): """Adds an element to the set.""" self.items.set(element, element) # Think of the data as a tuple, they both point to the same place in memeory self.size += 1 def remove(self, element): """Removes an element from the set.""" self.items.delete(element) self.size -= 1 def union(self, other_set): """ Returns a set that has that is a unity of two seperate sets""" union_set = Set() for key, value in self.items: union_set.add(key) for key, value in other_set.items: union_set.add(key) return union_set def intersection(self, other_set): """Returns a set that has common elements between two sets""" intersection_set = Set() for key, value in self.items: if other_set.contains(key): intersection_set.add(key) return intersection_set def difference(self, other_set): """Returns the unique elements in the first set""" difference_set = Set() for key, value in self.items: if not other_set.contains(key): difference_set.add(key) return difference_set def is_subset(self, other_set): """Checks if the set contains a part of the other set""" for key, value in self.items: if not other_set.contains(key): return False return True
class Set(object): def __init__(self, elements=None): """Initialize set as an empty hash table.""" self.table = HashTable() self.size = 0 if elements: for elem in elements: self.table.set(elem, None) # self.add(elem) self.size += 1 def __repr__(self): """Return a string representation of this Set.""" items = ['{!r}'.format(key) for key in self.table.keys()] return '{' + ', '.join(items) + '}' def __iter__(self): """Return iterable set.""" return iter(self.table.keys()) def contains(self, elem): """Returns True if element is in the set and False otherwise. Runnig time: O(1) since it is calling hashtable contains method""" # Pass the element as a key to call the hash table method contains(). return self.table.contains(elem) def add(self, elem): """Add element to this set, if not present already. Running time: O(1)""" if not self.contains(elem): # Credit goes to Zurich Okoren for correcting me to pass correct params(None) self.table.set(elem, None) self.size += 1 def remove(self, elem): """Removes item to the set if present, otherwise raise error. Running time: O(1)""" if self.contains(elem): self.table.delete(elem) self.size -= 1 else: raise KeyError("Element: {} not in set.".format(elem)) def discard(self, elem): """Removes item to the set if present, otherwise, stays silent. Running time: O(1)""" if self.contains(elem): self.table.delete(elem) self.size -= 1 def union(self, other_set): """Return a new set that is the union of this set and other_set Running time: O(n)? Space complexity: O(l) => l is number of elements gathered from both sets""" # copying the this set element to new_set new_set = Set(self.table.keys()) # now adds the other_set elements to the new set if not exist for elem in other_set: new_set.add(elem) return new_set def difference(self, other_set): """Return a new set that is the difference of this set and other_set Running time: Space complexity: """ new_set = Set() for elem in self: if other_set.contains(elem) == False: new_set.add(elem) return new_set def intersection(self, other_set): """Return a new set that is the union of this set and other_set Running time: Space complexity: """ new_set = Set() small_set = self if self.size >= other_set.size else other_set large_set = self if self.size < other_set.size else other_set # iterate through only small_set, so for elem in small_set: if large_set.contains(elem): # found match from the large set new_set.add(elem) return new_set def symmetric_difference(self, other_set): """Return a new set that is the difference of both sets""" new_set = Set() # elements set1 has but not set 2 for elem in self: if other_set.contains(elem) == False: new_set.add(elem) for elem in other_set: if self.contains(elem) == False: new_set.add(elem) return new_set def is_subset(self, other_set): """Return a boolean indicating whether other_set is a subset of this set Running time: Space complexity: """ if self.size <= other_set.size: for elem in self: if other_set.contains(elem) == False: return False return True return False
class Set(object): def __init__(self, elements=None): """Initialize a new empty set structure and add each elements if a sequence is given """ self.set = HashTable() self.size = 0 if elements is not None: for element in elements: self.add(element) def contains(self, element): ''' returns a boolean indicating whether element is in this set ''' return self.contains(element) def add(self, element): ''' adds an element to this set, if not present already ''' if self.contains(element): raise ValueError("{} already exists in the set.").format(element) else: self.set.set(element, None) self.size += 1 def remove(self, element): ''' removes an element from this set, if present, or else raise KeyError ''' if self.contains(element): self.set.delete(element) self.size -= 1 return else: raise KeyError("{} doesn't exist in the set").format(element) def union(self, other_set): ''' returns a new set that is the union of this set and other_set ''' # for key, value in other_set.items(): # # check if the current set has # # the same elements in the other set # if not self.contains(key): # self.add(key) # # else: def intersection(self, other_set): ''' returns a new set that is the intersection of this set and other_set ''' new_set = Set() for key in other_set.keys(): if self.contains(key): new_set.add(key) return new_set def difference(self, other_set): ''' returns a new set that is the difference of this set and other_set ''' new_set = Set() for key in other_set.keys(): if not self.contains(keys): def is_subset(self, other_set): '''
class HashSet(object): """Implement set class with a hash table.""" def __init__(self, elements=None): """Initialize the empty Set, and add each element a if sequence is given.""" self.collection = HashTable() self.size = 0 # Tracks the number of elements in constant time if elements: for element in elements: self.add(element) def __str__(self): """Return a formatted string representation of this set.""" elements_as_str = [ '{}'.format(repr(element)) for element in self.elements() ] return '{' + ', '.join(elements_as_str) + '}' def __repr__(self): """Return a string representation of this set.""" return 'Set({})'.format(repr(self.elements())) def elements(self): """Return a list of all elements in this set.""" return self.collection.keys() def add(self, element): """Add element to this set, if not present already.""" unit_type = True # TODO: What to return? Nothing? How does the set work? How many passes are there? self.collection.set(element, unit_type) self.size = self.collection.size # self.size += 1 def remove(self, element): """Remove element from this set, if present.""" # TODO: Do we return the element? what if it's not found?? try: self.collection.delete(element) self.size = self.collection.size except KeyError as error: raise ValueError('Element not found: {}'.format(element)) # self.size -= 1 # try: # self.collection.delete(element) # self.size = self.collection.size # except KeyError as error: # print('do something with the error') def contains(self, element): """Return true if element is in this set, false Otherwise.""" # TODO: Early exit check for size before calling a O(n) worst operation return self.collection.contains(element) def union(self, other_set): """Return the union of this set and other_set.""" # What is the union of two sets? # Union is the set of all elements in both sets # AuB = {x: x -> A or x -> B} # AuB is the set of elements which are in A, in B, or both A and B. union = HashSet(self.elements()) for element in other_set.elements(): union.add(element) return union def intersection(self, other_set): """Return the intersection of this set and other_set.""" # What is the intersection of two sets? # The new set with elements common to both sets. intersection = HashSet() for element in other_set.elements(): if self.contains(element): intersection.add(element) return intersection def difference(self, other_set): """Return the difference of this set and other_set.""" # What is the difference of two sets? # Remove the elements of B contained in A. # A - B = A \ B = { x E A | x nE B} # The new set with elements in this this set, but not in the other. difference = HashSet() # for element in other_set.elements(): # if not self.contains(element): # difference.add(element) # return difference for element in self.elements(): if not other_set.contains(element): difference.add(element) return difference def is_subset(self, other_set): """Return whether other_set is a subset of this set.""" # What is a subset of two sets? # Tests whether every element in this set is in the other_set for element in self.elements(): if not other_set.contains(element): return False return True
class HashSet: def __init__(self, items=[]): self.table = HashTable() for item in items: self.add(item) @property def size(self): return len(self.table) def __contains__(self, item): ''' Special method allowing use of `in` ''' return item in self.table def __iter__(self): ''' Special method allowing use of looping. ''' for item in self.table.keys(): yield item def __str__(self): return '{' + f'{", ".join([str(i) for i in self])}' + '}' def __repr__(self): return repr(self.table) def add(self, item): self.table.set(item, None) def remove(self, item): self.table.delete(item) def __len__(self): ''' Special method allowing use of `len()`. ''' return self.size def _smaller_larger_pair(self, set_1, set_2): ''' Helper to return the ordering of smaller, larger. ''' if len(set_1) < len(set_2): return set_1, set_2 return set_2, set_1 def __iand__(self, other_set): for item in self: if item not in other_set: self.remove(item) return self def __and__(self, other_set): return self.intersection(other_set) def intersection(self, other_set): ''' Find items that are present in both sets. ''' # Get the smaller, larger pair smaller, larger = self._smaller_larger_pair(self, other_set) new_set = HashSet() for item in smaller: if item in larger: new_set.add(item) return new_set def _assert_type(self, compared, symbol): if not isinstance(compared, HashSet): raise TypeError(f'unsuported operand type(s) for \ {symbol} \'{type(self)} and \'{type(compared)}\'') def __add__(self, other_set): self._assert_type(other_set, '+') return self._union(other_set) def __ior__(self, other_set): self._assert_type(other_set, '|=') for item in other_set: self.add(item) return self def __or__(self, other_set): self._assert_type(other_set, '|') return self.union(other_set) def _union(self, other_set): new_set = HashSet() for item in self: new_set.add(item) for item in other_set: new_set.add(item) return new_set def __isub__(self, other_set): self._assert_type(other_set, '-=') if len(self) < len(other_set): for item in self: if item in other_set: self.remove(item) else: for item in other_set: if item in self: self.remove(item) return self def __sub__(self, other_set): self._assert_type(other_set, '-') return self._difference(other_set) def _difference(self, other_set): new_set = HashSet() for item in self: if item not in other_set: new_set.add(item) return new_set def is_subset(self, other_set): if len(self) > len(other_set): return False for item in self: if item not in other_set: return False return True
class Set(object): def __init__(self, elements=None): # intilaize the size of the set, starts with intial size of 10 if elements is None: initial_size = 10 else: initial_size = len(elements) # self.data = HashTable(initial_size) for item in elements: if self.data.contains(item): continue else: self.data.set(item, None) def __str__(self): return str(self.data.keys()) def set_contents(self): """Get the contents of the set [key inside a HashTable]""" return self.data.keys() def size(self): """Find size of the set""" return self.data.size def contains(self, element): """return a boolean contained inside of the set [key inside a HashTable]""" """Best case running time for contains is O(1) near beginning of set Worst case running time for contains O(n) near end of set """ return self.data.contains(element) def add(self, element): """Add the element of the set""" # O (1) """Best case running time: O(1) near beginning of list of keys Worst case running time: O(n) near end of list of keys """ if self.contains(element): return else: self.data.set(element, None) def remove(self, element): # Raise value error if not available if self.contains(element): self.data.delete(element) else: raise ValueError("Element not in set") def union(self, second_set): """Return a new set, that is a union of first_set and second_set""" # O(n) since it goes through every item and has contains""" # create a new set that has the set conents result_set = self.set_contents() for item in second_set.set_contents(): if self.contains(item): continue else: result_set.append(item) return Set(result_set) def intersection(self, second_set): """Return a new set, that is intersection of this set and second_set.""" """O(n) since it goes through every item and has contains""" # create an empty set result_set = [] for item in second_set.set_contents(): # check if the set contains the item if self.contains(item): result_set.append(item) # else: # return ValueError("Set is empty") return Set(result_set) def is_subset(self, second_set): """Return True if second set is a subset of this set,else False""" # O(n); goes through every item and has contains # Compariing the size of the 2 set # to make sure if set is in the second set # for bucket in self.buckets: # for element in bucket.iterate(): # if not other.contains(element) if self.size() <= second_set.size(): for item in self.set_contents(): if second_set.contains(item): continue else: return False return True else: return False
class Set: def __init__(self, elements=None): """Initialize this Set list and append the given items, if any.""" self.data = HashTable() # Using the hashtable functions # self.size = self.data.size # Append the given elements if elements is not None: for element in elements: self.add(element) def __str__(self): """Return a formatted string representation of this Set.""" items = ['({!r})'.format(item) for item in self.data.keys()] return '[{}]'.format(' -> '.join(items)) def __repre__(self): """Return a string representation of this Set.""" return 'Set({!r})'.format(self.data.keys()) # Thank you Connor! @property def size(self): """ Best and worst case running time: O(1) """ return self.data.size def length(self): """Return the length of this Set using the hashtable function. Best and worst case running time: O(1)""" return self.data.length() def contains(self, element): """Returns a boolean indicating whether element is in this set. Best and worst case running time: O(1)""" return self.data.contains(element) def add(self, element): """Adds an element to this set, if not present already Best and worst case running time: O(1) (O(n) if resize is called)""" # If element is not present in list if self.data.contains(element) == False: self.data.set(element, element) def remove(self, element): """Remove element from this set, if present, or else raise KeyError Best and worst case running time: O(1)""" if self.data.contains(element) == True: self.data.delete(element) else: raise KeyError("Item doesn't exist in Set.") def union(self, other_set): """Returns a new set that is the union of this set and other_set Best and worst case running time: O(n)""" combined = [item for item in self.data.keys()] combined.extend(item for item in other_set.data.keys()) return Set(combined) def intersection(self, other_set): """Returns a new set that is the intersection of this set and other_set Best and worst case running time: O(n)""" # Thank you Connor! intersection = Set() larger = self if self.length() >= other_set.length() else other_set smaller = self if self.length() < other_set.length() else other_set # O(n) for element in larger.data.keys(): if smaller.contains(element): intersection.add(element) return intersection def difference(self, other_set): """Returns a new set that is the difference of this set and other_set Best and worst case running time: O(n)""" difference = Set() # O(n) for element in self.data.keys(): if other_set.contains(element) == False: difference.add(element) return difference def is_subset(self, other_set): """Returns a boolean indicating whether other_set is a subset of this set Best and worst case running time: O(n)""" if other_set.length() < self.length(): return False for element in self.data.keys(): if not other_set.contains(element): return False return True
class Set(object): def __init__(self, elements=None): """ Initialize this set """ self.size = 0 self.items = HashTable() # Adding elements to the hashtable if elements is not none if elements is not None: for element in elements: self.items.set(element, element) def __iter__(self): for item in self.items: yield item def get_items(self): """returns a list of all items in the set""" all_items = [] for item in self.items: all_items.append(item.data[0]) return all_items def contains(self, element): """ Return true if the element is in the set or false if is not """ return self.items.contains(element) def add(self, element): """ Add an element to the set """ self.items.set(element, element) self.size += 1 def remove(self, element): """ Delete an element from the set """ self.items.delete(element) self.size -= 1 def length(self): """ Return the size of the set """ return self.items.length() def union(self, other_set): """ Return the combination of elements in both sets """ new_set = Set() for item in self.items: new_set.add(item.data[0]) for item in other_set.items: new_set.add(item.data[0]) return new_set def intersection(self, other_set): """ Return the intersection between two sets """ new_set = Set() for item in self.items.values(): if other_set.contains(item): new_set.add(item) print("Intersection", new_set.items) return new_set def difference(self, other_set): """ Return elements that are not in other_set """ new_set = Set() intersection = self.intersection(other_set) for item in self.items: if not intersection.contains(item.data[0]): new_set.add(item.data[0]) return new_set def is_subset(self, other_set): """ return true if other set is a subset of this set and false if it isn't """ for item in other_set: if not self.contains(item.data[0]): return False return True
class HashSet(object): def __init__(self, elements=None): """Initialize set with the given initial size.""" self.size = 0 self.hashTable = HashTable() if elements is not None: for element in elements: if element is not None: self.add(element) def contains(self, element): """Returns a Boolean to indicate if an element is present in the set.""" return self.hashTable.contains(element) def add(self, element): """Adds an element to the set.""" if self.contains(element) == False: self.size += 1 self.hashTable.set(element, 0) # Raise error? def remove(self, element): """Removes an element from the set.""" if self.contains(element) == True: self.size -= 1 self.hashTable.delete(element) else: # Not found raise ValueError('Element not found: {}'.format(element)) def union(self, other_set): """Returns a new set containing all values from given set and self""" #TODO: Find better solution new_set = HashSet() # Add every item in self to new_set for element in self.hashTable.items( ): # use .keys() instead of .items() new_set.add(element[0]) # Loop over other_set, check if self contains element then add # (More natural) Add every element in other_set if it doesn't exist for element in other_set.hashTable.items(): if self.contains(element[0]) == False: new_set.add(element[0]) return new_set def intersection(self, other_set): """Returns a new set containing the values present in the given set and self""" new_set = HashSet() #TODO: Do I need to check which lenght is greater? # Adds items shared by both sets for element in self.hashTable.keys( ): # don't use self.hashTable.items() if other_set.contains(element): new_set.add(element) return new_set def difference(self, other_set): """Returns a new set that is the difference between self and the given set""" new_set = HashSet() #TODO: Find better solution for element in self.hashTable.items(): if other_set.contains(element[0]) == False: new_set.add(element[0]) for element in other_set.hashTable.items(): if self.contains(element[0]) == False: new_set.add(element[0]) return new_set def is_subset(self, other_set): """Returns a Boolean indicating if whether other_set is a sub set of this set""" intersection = self.intersection(other_set) if intersection.size == other_set.size: return True return False
class Set(): def __init__(self, elements=None): """Initialized this Set with the given data.""" self.items = HashTable() self.size = 0 if elements is not None: for item in elements: self.add(item) def length(self): """Calculates the length of the set. Runtime: O(n) where n is the number of times we iterate through the buckets to check the length """ return self.items.length() def contains(self, element): """Checks if the element is in the set. Runtime: O(1) constant time because we are just checking the value and using the hash function to check the bucket index """ return self.items.contains(element) def add(self, element): """Adds an element to the set. Runtime: O(1) constant time on average to hash the value and place it in a corresponding bucket """ self.items.set( element, element ) # Think of the data as a tuple, they both point to the same place in memeory self.size += 1 def remove(self, element): """Removes an element from the set. Runtime: O(1) constant time to find the bucket and delete the item """ self.items.delete(element) self.size -= 1 def union(self, other_set): """ Returns a set that has that is a unity of two seperate sets Runtime: O(n) where n is the amount of items we have to search through to add to the set """ union_set = Set() for key, value in self.items: union_set.add(key) for key, value in other_set.items: union_set.add(key) return union_set def intersection(self, other_set): """Returns a set that has common elements between two sets Runtime: O(n) where n is the amount of items we have to search through to add to the set """ intersection_set = Set() for key, value in self.items: if other_set.contains(key): intersection_set.add(key) return intersection_set def difference(self, other_set): """Returns the unique elements in the first set Runtime: O(n) where n is the amount of items we have to search through to add to the set """ difference_set = Set() for key, value in self.items: if not other_set.contains(key): difference_set.add(key) return difference_set def is_subset(self, other_set): """Checks if the set contains a part of the other set Runtime: O(n) where n is the amount of items we have to search through to check the items """ for key, value in self.items: if not other_set.contains(key): return False return True
class HashSet(object): """A Set data structure implemented using a HashTable.""" def __init__(self, elements=None): """Initialize a new empty set, and add any given elements.""" self.hashtable = HashTable() self.size = 0 # Add all provided elements provided. if elements: for element in elements: self.add(element) def elements(self): """Return all the elements in this set. Complexity: Best: Worst: Returns: list: a list containing all the elements in this set. """ return self.hashtable.keys() def contains(self, element): """Check whether element is in this set. Args: element: any -- what to check for in the set. Complexity: Best: Worst: Returns: bool: whether the element is in this set. """ return self.hashtable.contains(element) def add(self, element): """Add element to this set, if not present already. Args: element: any -- what to add to this set. Complexity: Best: Worst: """ if not self.contains(element): self.hashtable.set(element, None) self.size += 1 def remove(self, element): """Remove element from this set, if present. Args: element: any -- the element to remove from this set. Complexity: Best: Worst: Raises: KeyError: if the element is not in this set. """ self.hashtable.delete(element) # O(1), if element self.size -= 1 def union(self, other_set): """Return a new set that is the union of this set and other_set. Args: other_set: Set -- the set that will be combined with this set. Complexity: Best: Worst: Returns: Set: the union of the two sets. """ union = self # Loop through each element in the other set # O(s), where s is size of otherset for otherset_element in other_set.elements(): # Skip element if already in the union. # O(u), u is the number of all unique elements between each set. if union.contains(otherset_element): continue # add it to the union if not union.add(otherset_element) # O(1) return union # O(1) def intersection(self, other_set): """Return a new set that is the intersection of this set and other_set. Args: other_set: Set -- the set that will intersect this set. Complexity: Best: Worst: Returns: Set: the intersection between the two sets. """ intersection = HashSet() # O(1) # Loop through each element in the other set # O(n), where n is size of otherset for otherset_element in other_set.elements(): # Add element if it appears in both sets. # O(i), i is the number of all unique elements between each set. if self.contains(otherset_element): intersection.add(otherset_element) # O(1) return intersection # O(1) def difference(self, other_set): """Return a new set that is the difference of this set and other_set. Args: other_set: Set -- the set that will be compared to this set. Complexity: Best: Worst: Returns: Set: the difference between the two sets. """ difference = HashSet() # O(1) # Loop through each element in the other set # O(n), where n is size of otherset for otherset_element in other_set.elements(): # Skip element if it appears in both sets. # O(i), i is the number of all unique elements between each set. if self.contains(otherset_element): continue # add it if it's unique among both sets. difference.add(otherset_element) # O(1) return difference # O(1)
class HashSet: def __init__(self, elements=None): """initialize a new empty set structure, and add each element if a sequence is given""" self.hash = HashTable() self.size = 0 if elements != None: for element in elements: self.add(element) def size(self): """Property that tracks the number of elements in constant time. Runtime complexity: O(1) since we are constantly keeping track of the size everytime we add/remove an item. """ return self.size # def __contains__(self, item): # ''' Special method allowing use of `in` ''' # return item in self.table # def __iter__(self): # ''' Special method allowing use of looping. ''' # for item in self.table.items(): # yield item def contains(self, element): """return a boolean indicating whether element is in this set. Average case Rrntime complexity: O(1) since hashtable contains() function needs to find bucket index and traverse it's nodes to find the target element. """ return self.hash.contains(element) def add(self, element): """add element to this set, if not present already. Average runtime complexity: Average case O(1) since hashtable contains() function needs to find bucket index and traverse it's nodes to find the target element. Worst case runtime complexity: O(n) if we need to resize the hashtable due to load factor exceeding its efficient limit. """ if self.contains(element): raise KeyError( f"Cant add element to set more than once: {element}") else: self.hash.set(element, element) self.size += 1 def remove(self, element): """remove element from this set, if present, or else raise KeyError. Average case runtime complexity: O(1) since hashtable contains() function needs to find bucket index and traverse it's nodes to find the target element. Worst case runtime complexity: O(n) if we need to resize the hashtable if the load factor would benefit from reducing the size of the hashtable. """ if self.contains(element): self.hash.delete(element) self.size -= 1 else: raise KeyError(f"The element doesnt exist in the set: {element}") # def __len__(self): # ''' Special method allowing use of `len()`. ''' # return self.size def union(self, other_set): """return a new set that is the union of this set and other_set. Average case runtime complexity: O(n(1) + n(2)) because we are looping through both sets, and adding them together, excluding duplicates. We use n1 and n2 since each set may have different sizes. """ new_set = HashSet() for element in self.hash.values(): new_set.add(element) # Add the other_set elements, avoiding duplicates for element in other_set.hash.values(): if not new_set.contains(element): new_set.add(element) return new_set # def _smaller_larger_check(self, set1, set2): # if len(set1) > len(set2): # return set2, set1 # return set1, set2 def intersection(self, other_set): """return a new set that is the intersection of this set and other_set. Average case runtime complexity: O(m) where m is the smaller sized set. This is because we are looping through each element in the set. """ # smaller, larger = self._smaller_larger_check(self, other_set) new_set = HashSet() for element in self.hash.values(): if other_set.contains(element): new_set.add(element) # for element in smaller: # if element in larger: # new_set.add(element) return new_set def difference(self, other_set): """return a new set that is the difference of this set and other_set. Average case runtime complexity: O(n) since we are looping through each element in self set. """ new_set = HashSet() for element in self.hash.values(): if not other_set.contains( element ): # Check if the element does not exist in the other_set. new_set.add(element) # If element does exist in other_set, then don't add element and loop to the next one. return new_set def is_subset(self, other_set): """return a boolean indicating whether other_set is a subset of this set. Best case runtime complexity: O(1) if the self set is bigger than the other_set. Average case runtime complexity: O(n) if self set is smaller than the other_set, where we would loop through all the elements in the set to check if all elements exist in other_set. """ if self.size > other_set.size: return False else: count = 0 for element in self.hash.values(): if other_set.contains(element): # increment count variable everytime a matching element is found in other_set. count += 1 # return bool for whether the size of self set matches the number of elements matching in other_set. return self.size == count
class HashSet(object): def __init__(self, elements=None): """Initialize this hash set; add the given items, if any""" self.ht = HashTable() self.size = 0 if elements: for element in elements: self.add(element) def elements(self): """Return all of the elements in this set""" return self.ht.keys() def contains(self, element): """Return True if the given element is in this set, returns False otherwise. Best case running time: Omega(?) ? Worst case running time: O(?) ?""" if self.size > 0 and self.ht.contains(element): return True return False def add(self, element): """Add the given element to this set""" if self.ht.contains(element): raise ValueError('Element already exists') self.ht.set(element, True) self.size += 1 def remove(self, element): """Remove the given element from this set, or raise ValueError""" if not self.contains(element): raise ValueError('Element not found: {}'.format(element)) self.ht.delete(element) self.size -= 1 def union(self, other_set): """Returns the union of other_set and this set""" union_set = HashSet(self.elements()) for item in other_set.elements(): union_set.add(item) return union_set def intersection(self, other_set): """Returns the intersection of other_set and this set, if any elements are shared.""" intersection_set = HashSet() for item in self.elements(): if other_set.contains(item): intersection_set.add(item) return intersection_set def difference(self, other_set): """Returns the differemce of other_set and this set, if any elements are not shared.""" difference_set = HashSet() for item in self.elements(): if not other_set.contains(item): difference_set.add(item) return difference_set def is_subset(self, other_set): """Returns True if other_set is a subset of this set, returns False otherwise.""" for item in other_set.elements(): if not self.contains(item): return False return True
class Set(object): def __init__(self, elements=None): """Initialize this new empty set structure with the given initial size.""" self.map = HashTable() self.size = 0 # property that tracks the number of elements in constant time if elements is not None: for element in elements: self.size += 1 self.map.set(element, True) def contains(self, element): """return a boolean indicating whether element is in this set.""" # return element in self.elements -> return self.elements.___contains__(element) return self.map.contains(element) def add(self, element): """add element to this set, if not present already""" # check if its unique by # if not self.contains(element): if self.map.contains(element) == False: self.map.set(element, None) self.size += 1 return self.size def remove(self, element): """remove element from this set, if present, or else raise KeyError""" # if element in self.elements: # if self.elements.___contains__(element): # if self.contains(element): self.map.delete(element) self.size -= 1 return self.size # else: # raise KeyError('Element not found: {}'.format(element)) def union(self, other_set): """return a new set that is the union of this set and other_set""" new_set = Set() # for element in self.map: # for element in self.elements.__iter__(): for element in self.map.keys(): new_set.add(element) # or new_set.add(element.data[0]) ? for element in other_set.map.keys(): if not new_set.contains(element): new_set.add(element) return new_set def intersection(self, other_set): """return a new set that is the intersection of this set and other_set""" new_set = Set() for element in other_set.map.keys(): if self.contains(element): new_set.add(element) return new_set def difference(self, other_set): """return a new set that is the difference of this set and other_set""" new_set = Set() for element in self.map.keys(): if other_set.contains(element): new_set.add(element) return new_set def issubset(self, other_set): """Return true if all the elements in a set exist in the other set, False if not.""" for item in self.map.keys(): print('item in test_set:', item) if item not in other_set.map.keys(): return False return True
def test_hash_table_removes_correctly(self): ht = HashTable(16) ht.put("key-0", "val-0") ht.put("key-1", "val-1") ht.put("key-2", "val-2") ht.put("key-3", "val-3") ht.put("key-4", "val-4") ht.put("key-5", "val-5") ht.put("key-6", "val-6") ht.put("key-7", "val-7") ht.put("key-8", "val-8") ht.put("key-9", "val-9") return_value = ht.get("key-0") self.assertTrue(return_value == "val-0") return_value = ht.get("key-1") self.assertTrue(return_value == "val-1") return_value = ht.get("key-2") self.assertTrue(return_value == "val-2") return_value = ht.get("key-3") self.assertTrue(return_value == "val-3") return_value = ht.get("key-4") self.assertTrue(return_value == "val-4") return_value = ht.get("key-5") self.assertTrue(return_value == "val-5") return_value = ht.get("key-6") self.assertTrue(return_value == "val-6") return_value = ht.get("key-7") self.assertTrue(return_value == "val-7") return_value = ht.get("key-8") self.assertTrue(return_value == "val-8") return_value = ht.get("key-9") self.assertTrue(return_value == "val-9") ht.delete("key-9") ht.delete("key-8") ht.delete("key-7") ht.delete("key-6") ht.delete("key-5") ht.delete("key-4") ht.delete("key-3") ht.delete("key-2") ht.delete("key-1") ht.delete("key-0") return_value = ht.get("key-0") self.assertTrue(return_value is None) return_value = ht.get("key-1") self.assertTrue(return_value is None) return_value = ht.get("key-2") self.assertTrue(return_value is None) return_value = ht.get("key-3") self.assertTrue(return_value is None) return_value = ht.get("key-4") self.assertTrue(return_value is None) return_value = ht.get("key-5") self.assertTrue(return_value is None) return_value = ht.get("key-6") self.assertTrue(return_value is None) return_value = ht.get("key-7") self.assertTrue(return_value is None) return_value = ht.get("key-8") self.assertTrue(return_value is None) return_value = ht.get("key-9") self.assertTrue(return_value is None)
class Sets(object): def __init__(self, elements=None): # Impement the set with a hashtable since we will have unique keys self.items = HashTable() self.size = 0 if elements is not None: for item in elements: self.add(item) def add(self, element): """Add an element to the set, only will add it if it is unique. Best case running time: O(1) under what conditions? Element is placed in a bucket with no collissions Worst case running time: O(c) under what conditions? Where c is the amount of entries in a bucket, this is in a hashtable with a high load factor""" # Only add the element if the element isnt already in the set if self.contains(element) == False: self.items.set(element, 0) self.size += 1 def contains(self, element): """Check to see if the given element is in the set. Best case running time: O(1) under what conditions? value is hashed and found in a bucket with no collisions Worst case running time: O(c) under what conditions? Where c is the amount of entries in a bucket, this is in a hashtable with a high load factor""" return self.items.contains( element) # Use the hashtable implmentation of contains def delete(self, element): """Add an element to the set, only will add it if it is unique. Best case running time: O(1) under what conditions? Key is placed in a bucket with no collissions Worst case running time: O(c) under what conditions? Where c is the amount of entries in a bucket, this is in a hashtable with a high load factor""" self.items.delete(element) self.size -= 1 def intersection(self, other_set): """Get the Union of the two sets(which elements are in both sets). Best case running time: O(n) under what conditions? Needs to iterate through the other set with entries n and then calls the contains which could run at best constant time Worst case running time: O(nm) under what conditions? Where n is the amount of entries in the other_set and m would be the runtime of calling the contains on a hashtable with a high load factor with many collissions.""" intersection_set = Sets() # Iterate through the keys of the other_set and see if any of the keys are in the set for element in other_set.items.keys(): if self.items.contains(element): # the key is in both sets, so we add it intersection_set.add(element) return intersection_set def union(self, other_set): """Get the intersection of the two sets (A new set with elements that are in both). Best case running time: O(n + m) under what conditions? Needs to iterate through the other set with entries n and then also needs to iterate through items in self with entries of m Worst case running time: O(nc + mf) under what conditions? Needs to iterate through the other set with entries n and then also needs to iterate through items in self with entries of m. Also, we call add which isnt always constant and when called on a hashtable with a high load factor and many collisions, it would yield a runtime of c and f respectively where c and f are the number of collisions in a bucket""" union_set = Sets() for element in self.items.keys( ): # Iterate through the set keys and add elements, duplicate elements will not be added union_set.add(element) for element in other_set.items.keys(): # Iterate through the other set and add the elements, duplicate elements will not be added union_set.add(element) return union_set def difference(self, other_set): """Get what is the difference of the two sets(what is in the set and not in the other_set) . Best case running time: O(n) under what conditions? Needs to iterate through the other set with entries n and then calls the contains which could run at best constant time Worst case running time: O(nm) under what conditions? Where n is the amount of entries in the other_set and m would be the runtime of calling the contains on a hashtable with a high load factor with many collissions.""" difference_set = Sets() for element in self.items.keys(): # opposite logic to the intersection if other_set.contains(element) == False: difference_set.add(element) return difference_set def is_subset(self, other_set): """Check to see if other_set is a subset of the set. Best case running time: O(n) under what conditions? Needs to iterate through the other set with entries n and then calls the contains which could run at best constant time Worst case running time: O(nm) under what conditions? Where n is the amount of entries in the other_set and m would be the runtime of calling the contains on a hashtable with a high load factor with many collissions.""" if self.items.size < other_set.items.size: return False for item in other_set.items.keys( ): # iterare through the other set and see if an element isnt in our set if self.contains(item) == False: return False # It looks like a key doesnt exist on our set, so we will return False return True # We iterated through the other_set and we didnt have a key that wasnt in our set, so we can return true
class HashSet(object): def __init__(self, elements=None): """Initialize this hash set""" self.set = HashTable() self.size = 0 # Count number of element entries if elements: for item in elements: self.add(item) def keys(self): return self.set.keys() def contains(self, element): """Check whether element is in this set""" # Uses the built in contains method, returns True or False return self.set.contains(element) def add(self, element): """Add element to this set, if not present already""" # Adding the element to the set self.set.set(key=element, value=None) # Increment the size self.size += 1 def remove(self, element): """Remove element from this set, if present""" # Removing the item self.set.delete(element) # Decrementing the size self.size -= 1 def union(self, other_set): """Return the union of this set and other_set""" # Creating a new set new_set = HashSet() # Getting the elements from the other_set other_set_elements = other_set.set.keys() # Adding all the elements to the new_set for element in other_set_elements: new_set.add(element) # Adding all the elements within the current set to the new_set for element in self.set: new_set.add(element) return new_set def intersection(self, other_set): """Return the intersection of this set and other_set""" # Contains the elements that are common common_elements = [] # Getting the elements from the other_set other_set_elements = other_set.set.keys() # HashSet current elements hash_set_elements = self.set.keys() # Iterate through the list for element in other_set_elements: if element in hash_set_elements: common_elements.append(element) return common_elements def difference(self, other_set): """Return the difference of this set and other_set""" # Contains the elements that are common common_elements = HashSet() # Getting the elements from the other_set other_set_elements = other_set.set.keys() # Getting the elements from current set current_set_elements = self.set.keys() # Iterate through the list for element in other_set_elements: if element not in current_set_elements: common_elements.add(element) # Iterathe through the second list for element in current_set_elements: if element not in other_set_elements: common_elements.add(element) return common_elements def is_subset(self, other_set): """Check whether other_set is a subset of this set""" # Check if an element is not in there other_set_elements = other_set.keys() # Loop through the other_set_elements for element in other_set_elements: if element not in self.keys(): return False return True
class Set(object): def __init__(self, elements=None): self.hashtable = HashTable() self.size = 0 if elements is not None: for element in elements: self.add(element) def contains(self, element): """Returns a boolean indicating whether element is in this set Time Complexity: O(1) >> hashtable lookup is a const operation on average case Space Complexity: O(n) >> n is a bucket size. """ if not self.hashtable: raise ValueError('Empty Hashtable') else: return self.hashtable.contains(element) def add(self, element): """Adds element to this set, if not present already Time Complexity: O(1) >> set method of hastable is const time Space Complexity: O(1) >> one new space is created for new element """ if self.contains(element) is True: return else: self.hashtable.set(element, None) self.size += 1 def remove(self, element): """Removes element from this set, if present, or else raise KeyError Time Complexity: O(n) >> delete method of hastable is const time Space Complexity: O(n) >> """ if self.contains(element) is False: raise KeyError('Element does not exist') else: self.hashtable.delete(element) self.size -= 1 def union(self, other_set): """Returns a new set that is the union of this set and other_set Time Complexity: O(n+m) >> two loops >> two different hashtables and each has own length Space Complexity: O(n+m) >> creating space for new each element one by one. n + m """ united_set = Set() # adding elements of self to united_set for element in self.hashtable.keys(): united_set.add(element) # adding elements of other_set to united_set for element in other_set.hashtable.keys(): united_set.add(element) return united_set def intersection(self, other_set): """Returns a new set that is the intersection of this set and other_set Time Complexity: O(n) >> travaersing through the hashtable to collect and compare the elements Space Complexity: O(n) >> creating space for new each element one by one """ inter_set = Set() # smaller set has to be iterated and its elements should be compared to larger set if self.size > other_set.size: big_set = self small_set = other_set else: big_set = other_set small_set = self for element in small_set.hashtable.keys(): if big_set.hashtable.contains(element) is True: inter_set.add(element) return inter_set def difference(self, other_set): """Returns a new set that is the difference of this set and other_set Time Complexity: O(n) >> travaersing through the hashtable to collect and compare the elements Space Complexity: O(n) >> creating space for new each element one by one """ differ_set = Set() for element in self.hashtable.keys(): if not other_set.hashtable.contains(element): differ_set.add(element) for element in other_set.hashtable.keys(): if not self.hashtable.contains(element): differ_set.add(element) return differ_set def is_subset(self, other_set): """Returns a boolean indicating whether other_set is a subset of this set Time Complexity: O(n) >> travaersing through the hashtable to collect and compare the elements Space Complexity: O(n) >> creating space for new each element one by one """ # smaller set has to be iterated and its elements should be compared to larger set if self.size > other_set.size: big_set = self small_set = other_set else: big_set = other_set small_set = self for element in small_set.hashtable.keys(): if big_set.hashtable.contains(element) is True: return True else: return False
class Set(object): def __init__(self, items = None): self.size = 0 self.hashtable = HashTable() if items is not None: for item in items: self.add(item) def __iter__(self): #allows it to be iterable return self._generator() def __len__(self): return self.size def __contains__(self, item): return self.hashtable.contains(item) def _generator(self): #helper function for iterable for item in self.hashtable.keys(): yield item def add(self, item): if not self.__contains__(item): self.hashtable.set(item, None) self.size += 1 def remove(self, item): if self.__contains__(item): self.hashtable.delete(item) self.size -= 1 def union(self, other_set): new_set = Set() for item in other_set: new_set.add(item) for item in self: new_set.add(item) return new_set def intersection(self, other_set): new_set = Set() for item in other_set: if self.__contains__(item): new_set.add(item) return new_set def difference(self, other_set): new_set = Set() for item in self: if not other_set.__contains__(item): new_set.add(item) return new_set def is_subset(self, other_set): for item in self: if not other_set.__contains__(item): return False return True # if __name__ == "__main__": # s = Set([1,2,3,4]) # print(s.hashtable.keys())
class Set(object): """Set Data Structure w/.""" def __init__(self, init_size=8): """Initialize this hash table with the given initial size.""" self.ht = HashTable(init_size) @property def size(self): """Return size of ht.""" return self.ht.size def contains(self, element): """Check if the element is store in set (self).""" return self.ht.contains(element) def add(self, element): """Add new element to set, if unique.""" self.ht.set(element, None) def remove(self, element): """Remove element from set if present. Else raise keyerror.""" self.ht.delete(element) # Key error is raised in function def union(self, other_set): """Return a new set that is the union of self and other_set.""" union_set = deepcopy(self) for item in other_set.ht.items(): union_set.add(item) return union_set def intersection(self, other_set): """Return a new set that is the intersection of self and other_set.""" intersection_set = Set() # Use smaller set in order to iterate less items and improve runtime if self.size < other_set.size: for item in self.ht.items(): if other_set.contains(item): intersection_set.add(item) else: # If other set is smaller than self for item in other_set.items(): if self.contains(item): intersection_set.add(item) return intersection_set def difference(self, other_set): """Return a new set that is the difference of self and other_set.""" difference_set = Set() for item in self.ht.items(): if not other_set.contains(item): difference_set.add(item) return difference_set def is_subset(self, other_set): """Return a boolean indicating whether other_set is a subset of this set.""" for item in other_set.ht.items(): if not self.contains(item): return False return True
class Set(object): def __init__(self, elements=None): self.size = 0 # set elememts to be hashtables self.elements = HashTable() # if elements is not None: # for i in elements: # self.append(i) ''' or use size property to use this function as property ''' # @property # def sizd(self): # return self.elements.size # return a boolean indicating whether element is in this set def contains(self, element): # check if the element is in the set if self.elements.contains(element): return True return False # add element to this set, if not present already def add(self, element): # get buckets of the set hashtable = self.elements # check if the key of the bucket exist, if not, add element to hashtable and plus size if not self.contains(element): self.size += 1 # key of hashtable is the element of set hashtable.set(element, None) else: raise ValueError("element not in set") # remove element from this set, if present, or else raise KeyError def remove(self, element): # get index of the hashtable if element not in self.elements.keys(): raise ValueError("element not in set") else: self.size -= 1 # use hashtable function to delete element, which is the key of hashtable self.elements.delete(element) # return a new set that is the union of this set and other_set def union(self, other_set): for k in other_set.elements.keys(): # self.add(k) self.elements.set(k, None) return self # return a new set that is the intersection of this set and other_set # loop through shorter set and use contain inside of for loop to reduce run time to the length of linkedlist def intersection(self, other_set): interset = Set() len_self = self.elements.length() len_other = other_set.elements.length() if len_self < len_other: # check if other set contain the key in self set keys for k in self.elements.keys(): if other_set.elements.contains(k): # add the key to new set interset.add(k) else: for k in other_set.elements.keys(): if self.elements.contains(k): interset.add(k) return interset # return a new set that is the difference of this set and other_set def difference(self, other_set): diff_set = Set() # add key that's in self but not in other set for k in self.elements.keys(): if not other_set.elements.contains(k): diff_set.add(k) # add key that's in other but not in self set for k in other_set.elements.keys(): if not self.elements.contains(k): diff_set.add(k) return diff_set # return a boolean indicating whether other_set is a subset of this set def is_subset(self, other_set): for k in other_set.elements.keys(): # if find a k of other set not in self, the subset not exist if not self.elements.contains(k): return False return True
class Set(object): def __init__(self, items=None): self.items = HashTable() # setup Hasttable # Insert everything if items is not None: for item in items: self.add(item) @property def size(self): """ Makes size an attribute """ return self.items.length() def add(self, item): """ Insert one item to the set if it doesn't already exist Time complexity: O(1) since we are using hash table """ if not self.items.contains(item): # check if item doesn't exist self.items.set(item, None) # add the item def length(self): """ Gets the length of the set Time complexity: O(1) since we store the length in a property""" return self.size def is_empty(self): """ Checks if the set is empty Time complexity: O(1) since we store the length in a property""" return self.size == 0 def contains(self, item): """ Checks if item is in the set Time Complexity: O(1) since Hash table access is constant time""" return self.items.contains(item) def remove(self, item): """ Check if item exists and remove it or raise Keyerror Time complexity: O(1) since accessing from Hashtable is constant time""" self.items.delete( item) # remove the item or the inner hashtable will raise error def union(self, other_set): """ Makes a union with the other set and returns a new set Time complexity: O(n) since getting the keys take linear time""" smaller = self.items larger = other_set.items if smaller.size > larger.size: smaller, larger = larger, smaller new_set = Set(larger.keys()) for item in smaller.keys(): new_set.add(item) return new_set def intersection(self, other_set): """ Makes an intersection between self and other set Time complexity: O(min(m,n)) since we iterate over the smaller set""" smaller = self.items larger = other_set.items if smaller.size > larger.size: smaller, larger = larger, smaller new_set = Set() for item in smaller.keys(): if larger.contains(item): new_set.add(item) return new_set def difference(self, other_set): """ Gets the difference between two sets and returns it. Time complexity: O(n) since the keys() method takes linear time""" return Set(x for x in self.items.keys() if not other_set.contains(x)) def is_subset(self, other_set): """ Checks if all the items in other_set are in self Time complexity: O(n) since we are calling the keys() method that takes linear time""" if other_set.size > self.size: return False return len(other_set.difference(self).items.keys()) == 0
def test_delete_non_existant_items(self): ht = HashTable() with self.assertRaises(KeyError): ht.delete('A')