简体   繁体   中英

How to simplify a repetitive function

Is there a way anyone can think of to simplify this function? I find much of this quite repetitive but having a hard time thinking of a way to make it more pythonic or cleaner. Relatively new to python, so I'd appreciate any recommendations.

def colorize(n):
    if n in range(0, 10):
        return selection[-1]
    elif n in range(10, 20):
        return selection[-2]
    elif n in range(20, 30):
        return selection[-3]
    elif n in range(30, 40):
        return selection[-4]
    elif n in range(40, 50):
        return selection[-5]
    elif n in range(50, 60):
        return selection[-6]
    elif n in range(60, 70):
        return selection[-7]
    elif n in range(70, 80):
        return selection[-8]
    elif n in range(80, 90):
        return selection[-9]
    elif n in range(90, 100):
        return selection[-10]
    else:
        return None

To get 1 for the range 0 to 10 and 2 for the range 10 to 20 you can use Python 3's floored integer division.

x = n // 10 + 1

You can then negate this and use this for your indexing

def colorize(n):
    if 0 <= n < 100:
        return selection[-(n // 10 + 1)]

If you do not return anything from a function it returns None , you do not explicitly have to return it

When you've got a bunch of repetitive code and are having a hard time seeing how to remove the repetition a good trick is to modify the pieces bit by bit so they slowly start to resemble each other. If you do it right you can make them match each other exactly.

It may seem longwinded, but the nice thing about this technique is it doesn't require any big leaps of insight. You can get there with small, incremental changes without having to stare and your code and think really hard .

Let me show you what I mean.


Step 1: Turn all the elif s into straight if s and remove the else . This makes them more obviously the same, and you should see that it doesn't change the code's behavior.

if n in range(0, 10):
    return selection[-1]
if n in range(10, 20):
    return selection[-2]
if n in range(20, 30):
    return selection[-3]
if n in range(30, 40):
    return selection[-4]
if n in range(40, 50):
    return selection[-5]
if n in range(50, 60):
    return selection[-6]
if n in range(60, 70):
    return selection[-7]
if n in range(70, 80):
    return selection[-8]
if n in range(80, 90):
    return selection[-9]
if n in range(90, 100):
    return selection[-10]

return None

Step 2: Calculate the numbers based on some common value. We want to extract a new variable i such that each case becomes literally identical to the rest. If we set i to 1, then 2, then 3, etc., we can do that.

Let's consider the first case:

 if n in range(0, 10): return selection[-1]

If i is 1 then 10 is i*10 , -1 is -i , and 0 is (i-1)*10 .

i = 1
if n in range((i-1)*10, i*10):
    return selection[-i]

We can do the same thing for the second case.

 if n in range(10, 20): return selection[-2]

The same formulas work. All we have to do is change i to 2!

i = 2
if n in range((i-1)*10, i*10):
    return selection[-i]

Rinse and repeat 10 times and we get this beauty:

i = 1
if n in range((i-1)*10, i*10):
    return selection[-i]
i = 2
if n in range((i-1)*10, i*10):
    return selection[-i]
i = 3
if n in range((i-1)*10, i*10):
    return selection[-i]
i = 4
if n in range((i-1)*10, i*10):
    return selection[-i]
i = 5
if n in range((i-1)*10, i*10):
    return selection[-i]
i = 6
if n in range((i-1)*10, i*10):
    return selection[-i]
i = 7
if n in range((i-1)*10, i*10):
    return selection[-i]
i = 8
if n in range((i-1)*10, i*10):
    return selection[-i]
i = 9
if n in range((i-1)*10, i*10):
    return selection[-i]
i = 10
if n in range((i-1)*10, i*10):
    return selection[-i]

return None

Step 3 : Now that we have 10 identical if statements it should be clear how to turn the whole thing into a loop. Loop from i=1 to i=10 and we've got it.

for i in range(1, 11):
    if n in range((i-1)*10, i*10):
        return selection[-i]

return None

There we go. All the repetitive stuff is gone.


Step 4: If you wanted to go a step further you could try to calculate the value of i that corresponds to n instead of taking the guess-and-check approach above. I'll leave that as an exercise for you (or for other answers). It's a nice optimization but it's in a different league than the type of refactoring I just laid out here.

The obvious way to simplify a repetitive function is to use a loop:

def colorize(n):
    for i in range(0,10):
        if n in range(i*10, (i+1)*10):
            return selection[-i+1]
    return None

I'm sure there's a better way to simplify your specific task, but a loop is a general pattern you should keep in mind when you see this kind of repetitive code.

Try this:

def colorize(n):
    for i in range(0,11):
        if n in range((i*10),(i*10)+10):
            return selection[-(i+1)]

You can try something like this,

def colorize(n):
    if n in range(0,100):
        return selection[-1*(n//10+1)]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM