2
\$\begingroup\$

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()
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

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 ...

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.