Sojimanatsu
Sojimanatsu

Reputation: 601

How to simplify nested If's in Python 3 for better performance and readability?

I have been trying to maximize the readability and eliminate the verbosity of the algorithm that I created to detect entities.

I have a function with this structure:

    def function(ex, pr):
    if ex[pr.start - 1] and not \
            pr.start - 1 < 0 and not \
            ex[pr.start - 1].is_space and not \
            ex[pr.start - 1].is_punct:
        words = ex[pr.start - 1]
    elif ex[pr.start - 2] and not \
            pr.start - 2 < 0 and not \
            ex[pr.start - 2].is_space and not \
            ex[pr.start - 2].is_punct:
        words = ex[pr.start - 2]
    elif ex[pr.start - 3] and not \
            pr.start - 3 < 0 and not \
            ex[pr.start - 3].is_space and not \
            ex[pr.start - 3].is_punct:
        words = ex[pr.start - 3]
    elif ex[pr.start - 4] and not \
            pr.start - 4 < 0 and not \
            ex[pr.start - 4].is_space and not \
            ex[pr.start - 4].is_punct:
        words = ex[pr.start - 4]
    else:
        words = ''
    return words

This solution works, however, there are lots of repeated structures here.

I tried range() function

 def function(ex, pr):
    global words
    for index in range(1, 5):
        if ex[pr.start - index] and not \
                pr.start - index < 0 and not \
                ex[pr.start - index].is_space and not \
                ex[pr.start - index].is_punct:
            words = ex[pr.start - index]
        else:
            words = ''
    return words

Also I tried for index in (1,2,3,4):

How can I simplify this structure to eliminate the multiple elif's and hardcoded numbers?

Any suggestions would be appreciated.

Upvotes: 0

Views: 83

Answers (1)

Ottotos
Ottotos

Reputation: 673

My suggestion would be to create a function that does the check:

def check(ex, pr, number):
    if ex[pr.start - number] and not \
        pr.start - number < 0 and not \
        ex[pr.start - number].is_space and not \
        ex[pr.start - number].is_punct:

        return True

    else:
        return False

This would simplify the other function to:

def function(ex, pr):
    if check (ex, pr, -1):
        words = ex[pr.start - 1]
    elif check (ex, pr, -2):
        words = ex[pr.start - 2]
    elif check (ex, pr, -3):
        words = ex[pr.start - 3]
    elif check (ex, pr, - 4):
        words = ex[pr.start - 4]
    else:
        words = ''

   return words

Or you could even use the loop. Note that I added a break statement to make sure it performs the same as the code where no loop is used

def function(ex, pr):
    global words
    for index in range(1, 5):
        if check(ex, pr, index):
            words = ex[pr.start - index]
            break    # <-- added a break here
        else:
            words = ''
    return word

Upvotes: 1

Related Questions