I wanted to ask for a code review for my implementation of Set
:
#!python
from linkedlist import Node, LinkedList
from hashtable import HashTable
class Set(object):
def __init__(self, elements=None):
if elements is None:
initsize = 5
else:
initsize = len(elements)
self.data = HashTable(initsize)
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 contents(self):
return self.data.keys()
def size(self):
"""Find size."""
return self.data.size
def contains(self, element):
return self.data.contains(element)
def add(self, element):
if self.contains(element):
return
else:
self.data.set(element, None)
def remove(self, element):
if self.contains(element):
self.data.delete(element)
else:
raise ValueError
def union(self, other_set):
"""Return a new set that is a union of this set and other_set"""
newset = self.contents()
for item in other_set.contents():
if self.contains(item):
continue
else:
newset.append(item)
return Set(newset)
def intersection(self, other_set):
"""Return a new set that is an intersection of this set + other_set."""
newset = []
for item in other_set.contents():
if self.contains(item):
newset.append(item)
return Set(newset)
def is_subset(self, other_set):
"""Return a boolean whether other set is a subset of this set."""
# Check to make sure if everything in THIS set is in the other
if self.size() <= other_set.size():
for item in self.contents():
if other_set.contains(item):
continue
else:
return False
return True
else:
return False
# set_set_test = Set()
set_test = Set([6, 7, 8, 9, 10])
set_test2 = Set([1, 2, 3, 4, 5])
result = set_test.intersection(set_test2)
print(result)
set_test2 = Set([4, 5, 6, 7, 8])
print(set_test)
print(set_test2)
set_test.add(1)
print(set_test)
print(set_test.intersection(set_test2))
print(set_test.union(set_test2))
print(set_test.is_subset(set_test2))
set_test = Set([1, 2, 3])
set_test2 = Set([1, 2, 3, 4, 5, 6, 7, 8])
print(set_test.is_subset(set_test2))
set_test = Set([1, 2, 3])
set_test2 = Set([1, 2, 3])
print(set_test.is_subset(set_test2))
set_test = Set([1, 2, 3, 4])
set_test2 = Set([1, 2, 3])
print(set_test.is_subset(set_test2))
set_test = Set([1, 2, 3, 4, 5])
set_test2 = Set([4, 5, 6, 7, 8])
print(set_test.is_subset(set_test2))
I passed all 7 unit-testing:
from set import Set
import unittest
class SetTest(unittest.TestCase):
def test_init(self):
test1 = Set(['A', 'B', 'C', 'E'])
assert test1.size() == 4
test1 = Set([])
assert test1.size() == 0
def test_add(self):
test1 = Set(['A', 'B', 'C', 'E'])
assert test1.size() == 4
test1.add('D')
assert test1.size() == 5
test1.add('D')
assert test1.size() == 5
test1.add('B')
assert test1.size() == 5
test1.remove('B')
assert test1.size() == 4
test1.add('B')
assert test1.size() == 5
def test_remove(self):
# Test basic
test1 = Set(['A', 'B', 'C', 'E'])
assert test1.contains('B') is True
assert test1.size() == 4
test1.remove('B')
assert test1.contains('B') is False
assert test1.size() == 3
with self.assertRaises(ValueError):
test1.remove('B')
def test_contains(self):
test1 = Set(['A', 'B', 'C', 'E'])
assert test1.contains('A') is True
assert test1.contains('B') is True
assert test1.contains('C') is True
assert test1.contains('D') is False
assert test1.contains('E') is True
assert test1.contains('F') is False
test1.remove('E')
assert test1.contains('A') is True
assert test1.contains('B') is True
assert test1.contains('C') is True
assert test1.contains('D') is False
assert test1.contains('E') is False
assert test1.contains('F') is False
test1.add('F')
assert test1.contains('A') is True
assert test1.contains('B') is True
assert test1.contains('C') is True
assert test1.contains('D') is False
assert test1.contains('E') is False
assert test1.contains('F') is True
test1.add('E')
assert test1.contains('A') is True
assert test1.contains('B') is True
assert test1.contains('C') is True
assert test1.contains('D') is False
assert test1.contains('E') is True
assert test1.contains('F') is True
def test_intersection(self):
# Typical test, should just have two elements
test1 = Set([1, 2, 3, 4, 5])
test2 = Set([4, 5, 6, 7, 8])
result = test1.intersection(test2)
assert result.contents() == [4, 5]
# If same, just in case
test1 = Set([1, 2, 3, 4, 5])
test2 = Set([1, 2, 3, 4, 5])
result = test1.intersection(test2)
assert result.contents() == [1, 2, 3, 4, 5]
# If none match
test1 = Set([1, 2, 3, 4, 5])
test2 = Set([6, 7, 8, 9, 10])
result = test1.intersection(test2)
assert result.contents() == []
# If both empty
test1 = Set([])
test2 = Set([])
result = test1.intersection(test2)
test1 = Set(['A', 'B', 'C', 'E'])
test2 = Set(['A', 'B', 'C', 'D'])
result = test1.intersection(test2)
assert result.contains('A') is True
assert result.contains('B') is True
assert result.contains('C') is True
assert result.contains('D') is False
assert result.contains('E') is False
def test_union(self):
# Typical use; should be all the way to 8, skip 4, 5
test1 = Set([1, 2, 3, 4, 5])
test2 = Set([4, 5, 6, 7, 8])
result = test1.union(test2)
assert result.contents() == [1, 2, 3, 4, 5, 6, 7, 8]
# Exact same copies, should be no prob
test1 = Set([1, 2, 3, 4, 5])
test2 = Set([1, 2, 3, 4, 5])
result = test1.union(test2)
assert result.contents() == [1, 2, 3, 4, 5]
# No overlap
test1 = Set([1, 2, 3, 4, 5])
test2 = Set([6, 7, 8, 9, 10])
result = test1.union(test2)
assert result.contents() == [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# Let's try it with letters now
test1 = Set(['A', 'B', 'C'])
test2 = Set(['A', 'B', 'C', 'D'])
result = test1.union(test2)
assert result.contains('A') is True
assert result.contains('B') is True
assert result.contains('C') is True
assert result.contains('D') is True
assert result.contains('E') is False
def test_subset(self):
# Should be false; two overlapping
test1 = Set([1, 2, 3, 4, 5])
test2 = Set([4, 5, 6, 7, 8])
assert test1.is_subset(test2) is False
# Should be true; set A within set B
test1 = Set([1, 2, 3])
test2 = Set([1, 2, 3, 4, 5, 6, 7, 8])
assert test1.is_subset(test2) is True
# Should be true; set A same as set B
test1 = Set([1, 2, 3])
test2 = Set([1, 2, 3])
assert test1.is_subset(test2) is True
# Should be false; set A bigger than set B
test1 = Set([1, 2, 3, 4])
test2 = Set([1, 2, 3])
assert test1.is_subset(test2) is False
# Should be false; set A not sharing anything with B
test1 = Set([1, 2, 3])
test2 = Set([4, 5, 6])
assert test1.is_subset(test2) is False
# Doing the same, but with characters
# Should be false; two overlapping
# Should be true; set A within set B
test1 = Set(['A', 'B', 'C'])
test2 = Set(['A', 'B', 'C', 'D'])
assert test1.is_subset(test2) is True
# Should be true; set A same as set B
test1 = Set(['A', 'B', 'C'])
test2 = Set(['A', 'B', 'C'])
assert test1.is_subset(test2) is True
# Should be false; set A bigger than set B
test1 = Set(['A', 'B', 'C', 'D'])
test2 = Set(['A', 'B', 'C'])
assert test1.is_subset(test2) is False
# Should be false; set A not sharing anything with B
test1 = Set(['A', 'B', 'C', 'D'])
test2 = Set(['X', 'Y', 'Z'])
assert test1.is_subset(test2) is False
if __name__ == '__main__':
unittest.main()
1 Answer 1
When writing library classes you should follow the python guidelines to enable generic duck typed interfacing. have a look at the python datamodel and try to make e. g. the following tests work by implementing __len__
and __contains__
.
def test_len(self):
test1 = Set(['A', 'B', 'C', 'E'])
assert len(test1) == 4
def test_in(self):
test1 = Set(['A', 'B', 'C', 'E'])
assert 'A' in list1
there are more methods to implement. you probably want to iterate over your set for e in Set(['A', 'B', 'C', 'E']):
and more ...