chachacha
chachacha

Reputation: 338

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

Upvotes: 3

Views: 887

Answers (5)

Iain Shelvington
Iain Shelvington

Reputation: 32314

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

Upvotes: 3

John Kugelman
John Kugelman

Reputation: 362197

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 elifs into straight ifs 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.

Upvotes: 4

Nebiyou Yismaw
Nebiyou Yismaw

Reputation: 800

You can try something like this,

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

Upvotes: 0

Dipender Singh
Dipender Singh

Reputation: 1

Try this:

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

Upvotes: 0

divibisan
divibisan

Reputation: 12165

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.

Upvotes: 0

Related Questions