Search code examples
pythontime-complexityreadability

Best way to handle large if/else


I have a very large if/else block that that will be performing operations on a byte array. The id can technically be any number from 0x001 to 0xFFF, but they are generally known. each case is unique, and will perform calculations on different bytes in the array. the messages come from a queue at a rate of around .5ms - 1ms and get processed by this method

While the large if/else works, the biggest problem I see with it is that if, in this example, the id is 1222, we have to hit all of the previous ifs. Also as more messages are added the time complexity grows and it can get obnoxiously large.

def calcCanMessage(self):
    while: True
        #get msg - simplified for example
        msgId = msg.id
        msgData = msg.data
        if msgId == 324:
            #do something with msgData
            continue
        elif msgId == 211:
            continue
        elif msgId == 322:
            continue
        elif msgId == 321:
            continue
        elif msgId == 320:
            continue
        elif msgId == 342:
            continue
        elif msgId == 338:
            continue
        elif msgId == 24:
            continue
        elif msgId == 212:
            continue
        elif msgId == 323:
            continue
        elif msgId == 210:
            continue
        elif msgId == 209:
            continue
        elif msgId == 208:
            continue
        elif msgId == 642:
            continue
        elif msgId == 880:
            continue
        elif msgId == 1088:
            continue
        elif msgId == 865:
            continue
        elif msgId == 864:
            continue
        elif msgId == 882:
            continue
        elif msgId == 1595:
            continue
        elif msgId == 1090:
            continue
        elif msgId == 885:
            continue
        elif msgId == 884:
            continue
        elif msgId == 1224:
            continue
        elif msgId == 1761:
            continue
        elif msgId == 1762:
            continue
        elif msgId == 1245:
            continue
        elif msgId == 1219:
            continue
        elif msgId == 1217:
            continue
        elif msgId == 1222:
            continue
        else:
            print('unknown ID: ', msgId)

Solution

  • First, define the functions that do (different) things with msgData. The function bodies will be whatever you're currently doing in each block of the if..else statement.

    def msgId_324(msgData):
        #do something with msgData
    
    def msgId_211(msgData):
        #do something else with msgData
    
    # more functions to handle msgData
    

    Then define a dictionary to pair all the message ID values with their corresponding function.

    msgId_dict = {324: msgId_324, 
                211: msgId_211,
                # more msgId: msg_function pairs
                }
    

    Now you can replace the if statement with a dictionary lookup, which will be much faster, no matter how many message values, and call the returned function.

    msgId = msg.id
    msgData = msg.data
    
    if msgId in msgId_dict:
        msg_function = msgId_dict[msgId]
        msg_function(msgData)
    else:
        # optional else case to handle unrecognized message IDs