Tiago Verissimo
Tiago Verissimo

Reputation: 13

How do I change the __lt__ magical method so this algorithm can work ? - Python

Python Sorting Problem

I have a sorting algorithm problem, that consists in sorting objects of sublclass Priority Person(this objects will be placed in a list and the goal is to change the lt method of the subclass priority person to have a influence on the .sort() method on lists), if an object of Priority Person has a deficiency which is described by the parameter True it should be considered LESS than a priority person object that got the parameter False(which means that this person does not have any deficiency), in case both got deficiency or they both don't have deficiency it should be consider the lexicographical order of the first name of the priority persons involved. The main class of the sublclass of Priority Person is the class Person as I show above :

class Person(object):

    def __init__(self, name):
        """Create a person"""
        self.name = name
        try:
            lastBlank = name.rindex(' ')
            self.lastName = name[lastBlank + 1:]
        except:
            self.lastName = name
        self.birthday = None

    def __lt__(self, other):
        """Returns True if self's name is lexicographically
           less than other's name, and False otherwise"""
        return self.name < other.name

    def __str__(self):
        """Returns self's name"""
        return self.name

class PriorityPerson(Person): # the __lt__ part of this class does not work and I don't know why?

   def __init__(self,name,deficiencia):
        super().__init__(name)
        self.deficiente = deficiencia
    
    
    def __lt__(self, other):
        if self.deficiente and other.deficiente and self.name< other.name:
            return self.name < other.name
        elif self.deficiente and other.deficiente and other.name < self.name:
            return other.name< self.name
        elif self.deficiente and not other.deficiente and self.name < other.name:
            return self.name < other.name
        elif self.deficiente and not other.deficiente and other.name < self.name:
            return self.name< other.name
        elif not self.deficiente and other.deficiente and self.name < other.name:
            return other.name < self.name
        elif not self.deficiente and other.deficiente and other.name < self.name:
            return other.name < self.name
        elif not self.deficiente and not other.deficiente and self.name < other.name:
            return  self.name < other.name
        elif not self.deficiente and not other.deficiente and other.name < self.name:
            return other.name < self.name

Example of Implementation:

p1 = PriorityPerson("John Smith", False)
p2 = PriorityPerson("Sam Mendes", False)
p3 = PriorityPerson("Grandmother Anne", True)
p4 = PriorityPerson("Stephen Hawking", True)
p5 = PriorityPerson("Betty Large", True)

listaPessoas = [p1,p2,p3,p4, p5]
listaPessoas.sort()
for p in listaPessoas:
   print(p)

Correct output :

Betty Large
Grandmother Anne
Stephen Hawking
John Smith
Sam Mendes

My wrong output :

Betty Large
Stephen Hawking
Grandmother Anne
Sam Mendes
John Smith

Any help would be extremely appreciated. Thank You .

Upvotes: 1

Views: 320

Answers (2)

Błotosmętek
Błotosmętek

Reputation: 12927

You basically want to sort by priority and by name second. So, you have to compare for different priority first, and only with same priority, for name:

def __lt__(self, other):
    if self.deficiente != other.deficiente: # yes, you can compare bools!
        return self.deficiente
    else:
        return self.name < other.name

Upvotes: 0

ErdoganOnal
ErdoganOnal

Reputation: 880

I hope this works

class Person(object):
    def __init__(self, name):
        """Create a person"""
        self.name = name
        try:
            lastBlank = name.rindex(' ')
            self.lastName = name[lastBlank + 1:]
        except:
            self.lastName = name
        self.birthday = None

    def __lt__(self, other):
        """Returns True if self's name is lexicographically
        less than other's name, and False otherwise"""
        return self.name < other.name

    def __str__(self):
        """Returns self's name"""
        return self.name


class PriorityPerson(Person):
    def __init__(self, name, deficiencia):
        super().__init__(name)
        self.deficiente = deficiencia

    def __lt__(self, other):
        if self.deficiente and not other.deficiente:
            # If self is VIP and other is not, just return True
            return True
        elif not self.deficiente and other.deficiente:
            # If other is VIP and self is not, just return False
            return False

        # On equal priority, normal compare
        return super().__lt__(other)

p1 = PriorityPerson("John Smith", False)
p2 = PriorityPerson("Sam Mendes", False)
p3 = PriorityPerson("Grandmother Anne", True)
p4 = PriorityPerson("Stephen Hawking", True)
p5 = PriorityPerson("Betty Large", True)

listaPessoas = [p1,p2,p3,p4, p5]
listaPessoas.sort()
for p in listaPessoas:
   print(p)

The output:

Betty Large
Grandmother Anne
Stephen Hawking
John Smith
Sam Mendes

Upvotes: 1

Related Questions