Cedric Zoppolo
Cedric Zoppolo

Reputation: 4743

Obtain difference between two lists of objects in Python using hash

My objective is to get the difference between two lists containing objects.

I have implemented a class named Branch and overwritten its __eq__ and __ne__ methods as follows:

class Branch(object):
    def __str__(self):
        return self.name

    def __eq__(self, other):
        if isinstance(other, Branch):
            return (self.valueFrom == other.valueFrom) \
                and (self.valueTo == other.valueTo) \
                and (self.inService == other.inService)
        return NotImplemented

    def __ne__(self, other):
        result = self.__eq__(other)
        if result is NotImplemented:
            return result
        return not result

    def __init__(self, name, valueFrom, valueTo, inService=True):
        self.name = name
        self.valueFrom = valueFrom
        self.valueTo = valueTo
        self.inService = inService

My first attempt was to use the method difference from the set type. However it appears this is not possible as it uses the hash of the object and not the __eq__method as I would like to.

Following code shows the problem:

b1 = Branch("branch1", 1, 2)
b1b = Branch("equal to branch1", 1, 2)
b2 = Branch("branch2", 2, 3)
b3 = Branch("branch3", 3, 1)
b3_off = Branch("branch3 not in service", 3, 1, False)

l1 =[b1,b2,b3]
l2 =[b1b,b2,b3_off]

difference = set(l1).difference(l2)
for branch in difference:
    print branch

Output is:

>>> 
branch1
branch3

However I wish to get as output only branch3 as b1 and b1b should be treated as equal.

Is it possible to use sets to resolve this? Or should I approach the problem from a different perspective?

Upvotes: 2

Views: 549

Answers (1)

Padraic Cunningham
Padraic Cunningham

Reputation: 180441

You would need to implement hash, what you choose to is up to you but the following would work:

def __hash__(self):
    return hash((self.valueFrom , self.valueTo , self.inService))

All you need to implement is hash and eq:

class Branch(object):
    def __init__(self, name, valueFrom, valueTo, inService=True):
        self.name = name
        self.valueFrom = valueFrom
        self.valueTo = valueTo
        self.inService = inService

    def __eq__(self, other):
        if isinstance(other, Branch):
            return (self.valueFrom,self.valueTo,self.inService )\
                   ==(other.valueFrom, other.valueTo, other.inService)
        return NotImplemented

    def __str__(self):
        return self.name

    def __hash__(self):
        return hash((self.valueFrom, self.valueTo,self.inService))

Upvotes: 4

Related Questions