Search code examples
python-3.xclassfunctools

Make a class comparable so that I can get the max paremeter value of class instances within a list (Python)


I have a class that defines a single element (Request) and another class (RequestsBook) that is comprised from Request instances. The RequestsBook also has methods to append more requests into the book.

class Request:
    def __init__(self, req_id, req_type, value):
        self.req_id = req_id
        self.req_type= req_type
        self.value = value

class RequestsBook:
    def __init__(self):
        self.requests_book = list()

    def add(self, new_req):
        self.requests_book.append(new_req)

    def get_max_value_of_type(self, req_type):
        # pass

As seen above, I want to understand how I can efficiently get the maximum value of those Request instances inside the RequestsBook list that match a specific type.

For example:

rb = RequestsBook()
rb.add(Request(1, 'A', 100))
rb.add(Request(2, 'B', 42))
rb.add(Request(3, 'A', 78))
rb.add(Request(4, 'A', 12))

rb.get_max_value_of_type('A') # should return 190
rb.get_max_value_of_type('B') # should return 42 

Based on my understanding, I need to make the Request class comparable using the functools.total_ordering decorator.

I have never used this decorator before and I am struggling to think of an efficient way to implement get_max_value_of_type. Sadly, there are not many online examples for this use case. Any help will be much appreciated.


Solution

  • This code sorts by type then sorts by value then retrieves the maximum as the last item. It uses sorted builtin with a key function, attrgetter from the operator module. It follows the explanation in the Sorting HOWTO tutorial in Python docs (3.10).

    from operator import attrgetter
    
    class Request:
        def __init__(self,request=(None,None,None)):
            self.num, self.type, self.value = request
    
        def __repr__(self):
            return repr((self.num,self.type,self.value))
    
    class RequestsBook(Request):
        def __init__(rb):
            Request.__init__(rb)
            rb.bklist = []
            rb.typetp = ('A','B','C')
    
        def sortattr(rb,l,a):
            return sorted(l,key=attrgetter(a))
    
        def maxtype(rb):
            typel = rb.sortattr(rb.bklist,'type')
            maxl = []
            for t in rb.typetp:
                tl = [req for req in typel if req.type == t]
                mtl = rb.sortattr(tl,'value')
                maxl.append(mtl[-1])
            return maxl           
        
    inputl = [(1,'A',100),(2,'B',40),(3,'C',30),(4,'A',40),(5,'A',10),(6,'A',80),(7,'C',30),(8,'C',10),(9,'B',70),(10,'B',90)]
    bk = RequestsBook()
    bk.bklist = [Request(i) for i in inputl]
    maxtypel = bk.maxtype()
    print('input: ',inputl)
    print('output: ',maxtypel)