0

Trying to write a function to remove adjacent identical elements in a list. So [1,2,3,3,4] would return [1,2,3,4]

My codes as below:

def remove_adjacent(nums):
  for i in nums:
    if i == nums[nums.index(i)-1]:
        nums = nums.remove(i)
  return nums  

The result is returning the original list without modifying. Can someone educate me why?

Tom Karzes
  • 22,815
  • 2
  • 22
  • 41

4 Answers4

1

The if block never runs for remove_adjacent([1, 2, 3, 3, 4]).

nums.index(i) will always give the first matching index. When i is 3 (either of the threes), nums.index(i) will return 2, so nums[nums.index(i)-1] will be nums[2 - 1] will be 2, and 3 == 2 will be False.

Therefore, return nums just returns the list, unmodified.

Kelly Bundy
  • 23,480
  • 7
  • 29
  • 65
Kache
  • 15,647
  • 12
  • 51
  • 79
1

Following @TomKarzes comment, there are several flaws in your logic:

  • you are iterating over the list while modifying it
  • you iterate over the items, and try to get their index with index which is a nonsense. If you need to iterate over indices just do that.
  • even if you did not remove items while iterating over the list, index only finds the first occurrence of an item.

One option with a loop could be:

def remove_adjacent(nums):
  out = []
  prev = None
  for num in nums:
    if num != prev:
      out.append(num)
    prev = num
  return out

remove_adjacent([1, 2, 3, 3, 4])
# [1, 2, 3, 4]

NB. If you want to update the original list in place, replace return out by nums[:] = out.

Another option could be to use itertools.groupby:

from itertools import groupby

out = [k for k, _ in groupby(nums)]
mozway
  • 194,879
  • 13
  • 39
  • 75
  • Thank you very much, and the comments! I now get the point that index only find the first occurrence. But not sure I follow the first two points. Are you saying I can't modify a list while iterating over it? Or you mean I should iterate over index for comparing adjacent items. I like the way you did to create a new list and I thought about that, but really want to try modify original list instead. – Duke He May 14 '23 at 21:44
  • Please read [this](https://stackoverflow.com/questions/6260089/strange-result-when-removing-item-from-a-list-while-iterating-over-it-in-python), what you can do is reassign the output to your original list in the end: `nums[:] = out` – mozway May 15 '23 at 04:44
0

A problem is that you try to use function array.index(i). Check the documentation. Index returns index of the first occurrence, so when your iterator equals to second 3, index returns index 2 instead of 3. And you get this in your if statement: 3 == nums[1], where nums[1] == 2. I would solve this problem this way:

def remove_adjacent(nums):
    for i in range(len(nums) - 1, 0, -1):
        if nums[i] == nums[i - 1]:
            del nums[i]
    return nums
0

firstly index will fetch only the first matching occurrence so avoid that. secondly to compare you need to retain the previously seen value and update it at the end of every iteration. thirdly remove method directly updates on the list itself so no need to reassign nums with remove list,in fact it only destroys the list.

the final code is given below

x=[1,2,3,3,4]
def remove_adjacent(nums):
  previous=nums[0]
  for i in nums:
    if previous==i and i!=nums[0]:
      nums.remove(i)
    previous=i
  return nums
remove_adjacent(x)
Vishnu Balaji
  • 175
  • 1
  • 11