1

I've been stuck on this for a while now. It sounds simple enough but here's the code I've been working with so far. Basically the function is passed a bunch of numbers in a list for example a_list = [1,2,3,3,4,3] and I should get [1,2,3,4,3]

def remove_doubles(a_list):
    print()
    new_list = []
    for i in range(len(a_list)):
        if a_list[i] != a_list[i+1]:  
            new_list.append(a_list[i])
        return new_list
Georgy
  • 12,464
  • 7
  • 65
  • 73
Brian
  • 81
  • 1
  • 3
  • 9
  • Does this answer your question? [Removing elements that have consecutive duplicates](https://stackoverflow.com/questions/5738901/removing-elements-that-have-consecutive-duplicates) – Georgy Jul 15 '20 at 08:44

5 Answers5

5

itertools.groupby makes very easy work of this:

In [28]: L = [1,2,3,3,4,3]

In [29]: answer = [k for k,_g in itertools.groupby(L)]

In [30]: answer
Out[30]: [1, 2, 3, 4, 3]

Or a simpler one liner:

In [33]: next(zip(*itertools.groupby(L)))
Out[33]: (1, 2, 3, 4, 3)
inspectorG4dget
  • 110,290
  • 27
  • 149
  • 241
1

You can use generator:

def remove_doubles(a_list):
    duplicate = None
    for item in a_list:
        if duplicate != item:
            duplicate = item 
            yield item

a_list = [1, 2, 3, 3, 4, 3]
print(list(remove_doubles(a_list))) # [1, 2, 3, 4, 3]

It check if last item isn't the same as current, and if isn't returns it. Otherwise goes to the next item from the list and process starts from the beginning. As you can see, I used initial value for duplicate as None, so we can make a first comparison during first iteration.

turkus
  • 4,637
  • 2
  • 24
  • 28
0
>>> a_list = [1, 2, 3, 3, 4, 3]
>>> 
>>> def remove_doubles(a_list):
...     prev_item = a_list[0]
...     # the first item in our "to_return" list will be the first item in the input array
...     to_return = [prev_item]
...     i = 1
...     while i < len(a_list):
...         # if the current element equals the previous element, do nothing (i.e. don't append the current element)
...         if a_list[i] == prev_item:
...             pass
...         else:
...             # otherwise, reassign the current element to prev_item
...             # since we know it's unique, we can append it to our list to be returned
...             prev_item = a_list[i]
...             to_return.append(prev_item)
...         i += 1
...     return to_return
...             
... 
>>> remove_doubles(a_list)
[1, 2, 3, 4, 3]
blacksite
  • 12,086
  • 10
  • 64
  • 109
0

Maybe this is what you are looking for:

def remove_doubles(a_list):
    new_list = a_list[:1]
    for i in range(1, len(a_list)):
        if new_list[-1] != a_list[i]:
            new_list.append(a_list[i])
    return new_list

Edit:

If you're wanting to mutate a_list to remove adjacent duplicate values instead of simply returning a new list with them removed, you can simply change return new_list to a_list[:] = new_list.

  • Unfortunately it still returns the same passed values. – Brian Oct 03 '16 at 00:54
  • It hasn't done that for any of my test cases, including the `[1, 2, 3, 3, 4, 3]` case you provided. Can you provide an example? –  Oct 03 '16 at 00:58
  • Hi, passing this list [1, 1, 1, 3, 8, 8, 4, 3, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5] still gives me the same. – Brian Oct 03 '16 at 02:44
  • `[1, 3, 8, 4, 3, 6, 5]` is what gets printed when I use `print(remove_doubles([1, 1, 1, 3, 8, 8, 4, 3, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5]))`. Are you supposed to remove all doubles from the original list rather than returning a new list with all doubles removed? If so, see my edit. Otherwise, I don't know why you're getting different output from mine. –  Oct 03 '16 at 02:48
  • Hey, basically I'm wanting to remove all adjacent numbers from the original list. so [1, 1, 1, 3, 8, 8, 4, 3, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5] would give me [1,3,8,4,3,6,5] Sorry for the confusion. I hope this clears it. – Brian Oct 03 '16 at 03:27
  • Hey, quick question. Is there any way to return an empty list if I pass an empty list to the above function without getting the "list index out of range" error? thanks for your help! – Brian Oct 03 '16 at 03:47
  • @Brian You shouldn't get any index error because slicing a list doesn't cause an index error on the first line, and any indexing will occur inside the loop. For the code to enter the loop, there must be two elements in the list or more. Otherwise, you started with an empty list or a list with only one item. –  Oct 03 '16 at 09:59
  • basically I want the code to work even if I pass it an empty string. I could change the original 'new_list' assignment to an empty list '[]' but doing so will automatically remove the first element of any list being passed if its a double. eg: Passing '[1,1,1,2,4,2,5]' would give me '[2,4,2,5]' – Brian Oct 03 '16 at 19:51
  • The original new_list assignment will correctly result in an empty list if you pass an empty list to the function, else it will contain the first item in a_list. –  Oct 03 '16 at 19:53
  • Sorry I just figured it out. All I had to do was concatenate the first list element to the new list. Thanks for your help:) – Brian Oct 03 '16 at 19:55
-1

This should work.

def remove_doubles(a_list):
    new_list = [a_list[0]]
    for i in range(1, len(a_list)):
        if a_list[i] != a_list[i-1]:
            new_list.append(a_list[i])
    return new_list
geo1230
  • 242
  • 4
  • 15
  • Hey thanks for that. Any modification I can do to this if I wanted to pass an empty list without getting the "list index out of range" error? – Brian Oct 03 '16 at 04:51