1

I followed another post on here to create a function that receives a list of numbers and removes all adjacent duplicate numbers. It is working for all my test cases except the one below. The logic makes sense to me and I'm just not seeing where I'm going wrong. If anyone can help I'd greatly appreciate it.

def removeAdjacentNumbers(numList):
    previous = ''
    for i in numList[:]:
        if i == previous:
            numList.remove(i)
        else:
            previous = i
    return numList
    
def main():
    print(removeAdjacentNumbers([2,2,4,4,2,2,5,5]))

if __name__== "__main__":
    main()

It is returning: [4, 2, 2, 5] And is supposed to return: [2, 4, 2, 5]

  • Welcome to Stack Overflow! Please read about [How to debug small programs](http://ericlippert.com/2014/03/05/how-to-debug-small-programs/). You can also use [Python-Tutor](http://www.pythontutor.com/visualize.html#mode=edit) which helps to visualize the execution of the code step-by-step. It would be better if you came asking here ***after*** you tried some basic debug and can ask about what specifically you cannot fix. Right now it seems like you're not asking us to debug your code for you... – Tomerikoo Nov 09 '21 at 15:53
  • `remove` always removes the ***first*** occurrence it encounters. So by the time it reaches the last `2`, it will remove the second one, not the third (which is the adjacent one) – Tomerikoo Nov 09 '21 at 15:56

2 Answers2

2

You had a good start. Below is a fix of your code:

def removeAdjacentNumbers(numList):
    previous = None
    out = []              # define a new list for output
    for i in numList:     # no need to slice here
        if i != previous: # if we have a new value
            out.append(i) # we save it for output
        previous = i
    return out

The major issue was that you remove the first element of the list from the left.

If you really want to use your methods you should use pop with the index and not remove, and you should iterate over the list backwards to keep consistent index (or keep track of the number of deletion and subtract this to your pop value):

def removeAdjacentNumbers(numList):
    previous = ''
    for i, value in enumerate(numList[::-1]):
        if value == previous:
            numList.pop(len(numList)-i-1)
        else:
            previous = value
    return numList
mozway
  • 194,879
  • 13
  • 39
  • 75
  • Not precisely, the OP was iterating over `numList[:]` which is a copy of the list – Tomerikoo Nov 09 '21 at 15:57
  • 1
    Yes, right, but anyway, this has unexpected consequences, then enumerate and pop should be used – mozway Nov 09 '21 at 15:59
  • 2
    No, it is pretty expected. The real problem was that `remove` removes the first occurrence it finds so when reaching the second chink of `2`s it actually removed the first occurrence of it instead of the adjacent one... – Tomerikoo Nov 09 '21 at 16:01
  • 1
    I mean it has unexpected consequences as the method to remove is wrong, one should use pop and iterate over the list backwards, let me add an example – mozway Nov 09 '21 at 16:03
  • It is not unexpected if you read the docs... ;) (by *you* I mean the OP, or anyone else *not* reading the docs) – Tomerikoo Nov 09 '21 at 16:30
  • OK, but then nothing is unexpected unless there is a bug or hardware failure :p – mozway Nov 09 '21 at 16:34
1

@mozway is correct. Here is one of the many ways to do it, while altering the list when iterating over it. I just came with this quick approach.

i = 0
numList = [2, 2, 4, 4, 2, 2, 5, 5]

while i < len(numList)-1:
    if numList[i] == numList[i+1]:
        numList.pop(i)
    else:
        i += 1

print(numList)

I wonder how the time and space complexities are compared to @mozway's answer.

Abhishek
  • 412
  • 5
  • 17