0

I have a list for which I want to subtract element i+1 with element i. If result is greater than 2, element i must to be remove. I use a recursive function but I always get this error : IndexError: list index out of range

l = [10,11,12,20,21,22]  

def remove_Element():
    for i in range(len(l)-1):            
        if l[i+1]-l[i] > 2:
            l.remove(l[i])
            remove_Element()                
      
remove_Element() 

Could someone help me to fix it ?

Romain
  • 135
  • 9
  • Desired output? – Agent Biscutt Jan 11 '22 at 09:13
  • You need to be sure `i` is not at the end of the list before you access the `l[i+1]` index. So something like … `if i + 1 < len(l)-1 :` you can put that with your existing `if` first or wrap it. Make sense? – Jarvis Jan 11 '22 at 09:14
  • Consider that your program first executes a loop with 6 repetitions if you delete the list values inside the loop and access to larger elements is not possible due to their absence. –  Jan 11 '22 at 09:17
  • I don't understand why recursion is supposed to help solve the problem. The code already iterates over the list. – Karl Knechtel Jan 11 '22 at 09:30
  • @KarlKnechtel Recursion is not the best solution, but an iterative version would probably still have both a for-loop and a while-loop. From what I understand, the OP wants to remove elements repeatedly so that at the end, it is guaranteed that two adjacent elements differ by at most 2. – Stef Jan 11 '22 at 09:41
  • Although this could be clarified in the question. @Romain: What final list do you want when applying your function to `[10,11,12,20,21,22]`? – Stef Jan 11 '22 at 09:42

1 Answers1

1

A few issues:

  • If you use recursion, you should not keep looping after the recursive call has been made. Moreover, since then the list has become shorter, the loop will go too far, and produce the error you got. So a simple solution is to add a break or return immediately after the recursive call

  • remove is not the method you want to use, since it will look for a certain value. If that value occurs elsewhere before the current index, it will be that one that will be removed. This is not right. Use .pop(i) instead.

With those two fixes the code becomes:

def remove_Element():
    for i in range(len(l)-1):            
        if l[i+1]-l[i] > 2:
            l.pop(i)
            remove_Element()
            break

Still some remarks:

  • Be aware that the check is being repeated from the start when you make the recursive call, which explains why the value 10 is eventually being removed (after 12 has been removed, 11 gets removed, and then 10). I assume this is what you want. If not, you should pass as argument from which index you want to continue the removal logic:

    def remove_Element(start=0):
        for i in range(start, len(l)-1):            
            if l[i+1]-l[i] > 2:
                l.pop(i)
                remove_Element(i)
                break
    
  • Recursion is overkill here. This should better be done iteratively, also because the stack available for recursion is limited.

  • It may also be more appropriate not to mutate the given list, but create a new one that has the desired items.

  • Make the list a parameter to the function, so it is clear which list it is taking as input

trincot
  • 317,000
  • 35
  • 244
  • 286