Home > Blockchain >  I'm implementing a Set class from scratch in python but it's not working
I'm implementing a Set class from scratch in python but it's not working

Time:08-06

I'm trying to build the Set class from scratch in python but it's not working very well with the tester I was given.

The class works well with no coding errors but it's just not giving the expected results as it should. I'm not sure what's causing the proplem.

This is my class:

class mySet:
    def __init__(self, data = None):
        if data == None:
            self.elements = []
        else:
            self.elements = []
            if len(data) > 1:
                for i in data:
                    if i not in self.elements:
                        self.elements.append(i)

    def add(self, data):
        if data not in self.elements:
            self.elements.append(data)

    def pop(self):
        if len(self.elements) > 0:
            return self.elements.pop()
        raise KeyError('empty set!')
    
    def remove(self, key):
        if key in self.elements:
            self.elements.remove(key)
        else:
            raise KeyError('This value was not found in the set') 
    
    def discard(self, key):
        if key in self.elements:
            self.elements.remove(key)    
    
    def clear(self):
        if len(self.elements) > 0:
            self.elements.clear()
    
    def copy(self):
        from copy import copy
        return copy(self)
    
    def issubset(self, otherSet):
        return self.__le__(otherSet)
    
    def ispropersubset(self, otherSet):
        return self.__lt__(otherSet)
    
    def issuperset(self, otherSet):
        return self.__ge__(otherSet)
    
    def ispropersuperset(self, otherSet):
        return self.__gt__(otherSet)    
    
    def union(self, otherSet):
        return self.__or__(otherSet) 
    
    def intersection(self, otherSet):
        return self.__and__(otherSet)
    
    def difference(self, otherSet):
        return self.__sub__(otherSet)
    
    def symmetric_difference(self, otherSet):
        return self.__xor__(otherSet)
    
    def isdisjoint(self, otherSet):
        if len(self.__xor__(otherSet)) == 0:
            return True
        return False
    
    def update(self, otherSet):
        self.__ior__(otherSet)
        
    def intersection_update(self, otherSet):
        self.__iand__(otherSet)
    
    def difference_update(self, otherSet):
        self.__isub__(otherSet)
    
    def symmetric_difference_update(self, otherSet):
        self.__ixor__(otherSet)
    
    def __str__(self):
        return f'{self.elements}'
    
    def __repr__(self):
        return self.__str__()
    
    def __len__(self):
        return len(self.elements)   
    
    def __contains__(self, key):
        if key in self.elements:
            return True
        return False
    
    def __eq__(self, other):
        if isinstance(other, mySet):
            if self.elements == other.elements:
                return True
            return False
        return False
    
    def __ne__(self, other):
        if isinstance(other, mySet):
            if self.elements != other.elements:
                return True
            return False
        return False    
    
    def __le__(self, other):
        if isinstance(other, mySet):
            if self.elements <= other.elements:
                return True
            return False
        return False
    
    def __lt__(self, other):
        if isinstance(other, mySet):
            if self.__le__(other) and self.__ne__(other):
                return True
            return False
        return False
    
    def __ge__(self, other):
        if isinstance(other, mySet):
            if self.elements >= other.elements:
                return True
            return False
        return False    
    
    def __gt__(self, other):
        if isinstance(other, mySet):
            if self.__ge__(other) and self.__ne__(other):
                return True
            return False
        return False    
    
    def __or__(self, other):
        if isinstance(other, mySet):
            result = self.copy()
            for i in other.elements:
                result.add(i)
            return result
    
    def __and__(self, other):
        if isinstance(other, mySet):
            result = mySet()
            for i in self.elements:
                if i in other.elements:
                    result.add(i)
            return result
    
    def __sub__(self, other):
        if isinstance(other, mySet):
            result = mySet()
            for i in self.elements:
                if i not in other.elements:
                    result.add(i)
            return result    
            
    def __xor__(self, other):
        if isinstance(other, mySet):
            result = mySet()
            for i in other.elements:
                if i not in self.elements:
                    result.add(i)
            for j in self.elements:
                if j not in other.elements:
                    result.add(j)
            return result
        
    def __ior__(self, other):
            self.add(other.elements)
    
    def __iand__(self, other):
        result = self.__and__(other)
        self.elements = result
        
    def __isub__(self, other):
        result = self.__sub__(other)
        self.elements = result
    
    def __ixor__(self, other):
        result = self.__xor__(other)
        self.elements = result

this is the tester program if it's going to help: Tester program

It's going to be easier to just copy\paste the tester program because it's super long. the Tester doesn't have any issues it's just the set class.

This is the errors I'm getting:


    Error: init 7.  Expected: [1, 2, 3], Got: [1, 3, 2]
    Error: init 8.  Expected: [1, 2, 3], Got: [1, 3, 2]
    Error: init 10.  Expected: [1, 2, 3], Got: [1, 3, 2]
    Error: init 12.  Expected: True, Got: False
    Error: euqals 2.  Expected: True, Got: False
    Error: euqals 5.  Expected: False, Got: True
    Error: isdisjoint 1.  Expected: True, Got: False
    Error: isdisjoint 2.  Expected: True, Got: False
    Error: isdisjoint 5.  Expected: True, Got: False
    Error: isdisjoint 6.  Expected: True, Got: False
    Error: add 1.  Expected: [], Got: [1]
    Error: add 2.  Expected: [4, 2, 1, 3], Got: [1, 2, 3, 4]
    Error: update 1A.  Expected: [1, 2, 3, 4, 5], Got: [1, 2, 3, [3, 4, 5]]
    Error: update 2A.  Expected: [1, 2, 3], Got: [[1, 2, 3]]
    Error: update 3A.  Expected: [1, 2, 3], Got: [1, 2, 3, []]
    Error: update 4A.  Expected: [1, 2, 3], Got: [1, 2, 3, [1, 2, 3]]
    Error: union 2A.  Expected: [2, 3, 4, 5, 6], Got: [4, 5, 6, 2, 3, 4, 5]
    Error: union 3A.  Expected: [4, 5, 6], Got: [4, 5, 6, 2, 3, 4, 5]
    Error: union 4A.  Expected: [4, 5, 6], Got: [4, 5, 6, 2, 3, 4, 5, 4, 5, 6, 2, 3, 4, 5]
    Error: union 1B.  Expected: [1, 2, 3, 4, 5, 6], Got: [1, 2, 3, 4, 5, 6, 4, 5, 6, 2, 3, 4, 5, 4, 5, 6, 2, 3, 4, 5]
    Error: union 2B.  Expected: [2, 3, 4, 5, 6], Got: [4, 5, 6, 2, 3, 4, 5, 4, 5, 6, 2, 3, 4, 5, 2, 3, 4, 5]
    Error: union 3B.  Expected: [4, 5, 6], Got: [4, 5, 6, 2, 3, 4, 5, 4, 5, 6, 2, 3, 4, 5, 4, 5, 6, 2, 3, 4, 5, 2, 3, 4, 5]
    Error: union 4B.  Expected: [4, 5, 6], Got: [4, 5, 6, 2, 3, 4, 5, 4, 5, 6, 2, 3, 4, 5, 2, 3, 4, 5, 4, 5, 6, 2, 3, 4, 5, 4, 5, 6, 2, 3, 4, 5, 4, 5, 6, 2, 3, 4, 5, 2, 3, 4, 5]
    Error: difference 2A.  Expected: [], Got: [1]
    Error: difference 2B.  Expected: [], Got: [1]
    Error: symmetric_difference 1A.  Expected: [1, 2, 3, 4, 5, 6], Got: [4, 5, 6, 1, 2, 3]
    Error: symmetric_difference 2A.  Expected: [1, 4, 5], Got: [4, 5, 1]
    Error: symmetric_difference 1B.  Expected: [1, 2, 3, 4, 5, 6], Got: [4, 5, 6, 1, 2, 3]
    Error: symmetric_difference 2B.  Expected: [1, 4, 5], Got: [4, 5, 1]
    Error: discard 2.  Expected: [3, 2], Got: [2, 3]
    177 tests run.
    30 errors found

sorry if it's super long but it's what it is.

CodePudding user response:

A large number of the errors are because the __eq__() method simply compares the elements lists directly. When comparing lists, order is significant, but it shouldn't be significant for sets, and you're getting errors when the order is different.

If you assume that the elements all implement <, you can sort them before comparing.

    def __eq__(self, other):
        if isinstance(other, mySet):
            if sorted(self.elements) == sorted(other.elements):
                return True
            return False
        return False

This should fix all the ones where expected and got are the same except for order. It also fixes some of the "Expected: True Got: False" errors, because they're testing the result of == internally.

The logic of isdisjoin() is wrong. If the sets are disjoint, __xor__ will return a set that contains all the elements of both sets, since it returns all the elements that are in one but not in the other. You should use self.intersection(other) rather than self.__xor__(other).

The reason for the add 1, difference 2A, and difference 2B errors is because of the test if len(data) > 1: in __init__(). If you call mySet([1]), the length is 1, which is not greater than 1. Get rid of that test, it's not needed. If you really want to keep it, it should be if len(data) > 0:.

The logic of __ior__() is wrong. It's adding other.elements as a single element in the set, it needs to iterate over it:

def __ior__(self, other):
    for i in other.elements:
        self.add(i)

This is causing all the update errors.

All the union errors are because your original add() method didn't check for duplicates.

  • Related