Removing elements that have consecutive duplicates

I was curios about the question: Eliminate consecutive duplicates of list elements, and how it should be implemented in Python.

What I came up with is this:

list = [1,1,1,1,1,1,2,3,4,4,5,1,2]
i = 0

while i < len(list)-1:
    if list[i] == list[i+1]:
        del list[i]
    else:
        i = i+1

Output:

[1, 2, 3, 4, 5, 1, 2]

Which I guess is ok.

So I got curious, and wanted to see if I could delete the elements that had consecutive duplicates and get this output:

[2, 3, 5, 1, 2]

For that I did this:

list = [1,1,1,1,1,1,2,3,4,4,5,1,2]
i = 0
dupe = False

while i < len(list)-1:
    if list[i] == list[i+1]:
        del list[i]
        dupe = True
    elif dupe:
        del list[i]
        dupe = False
    else:
        i += 1

But it seems sort of clumsy and not pythonic, do you have any smarter / more elegant / more efficient way to implement this?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

>>> L = [1,1,1,1,1,1,2,3,4,4,5,1,2]
>>> from itertools import groupby
>>> [key for key, _group in groupby(L)]
[1, 2, 3, 4, 5, 1, 2]

For the second part

>>> [k for k, g in groupby(L) if len(list(g)) < 2]
[2, 3, 5, 1, 2]

If you don’t want to create the temporary list just to take the length, you can use sum over a generator expression

>>> [k for k, g in groupby(L) if sum(1 for i in g) < 2]
[2, 3, 5, 1, 2]

Method 2

Oneliner in pure Python

[v for i, v in enumerate(your_list) if i == 0 or v != your_list[i-1]]

Method 3

If you use Python 3.8+, you can use assignment expression :=:

list1 = [1, 2, 3, 3, 4, 3, 5, 5]

prev = object()
list1 = [prev:=v for v in list1 if prev!=v]

print(list1)

Prints:

[1, 2, 3, 4, 3, 5]

Method 4

A “lazy” approach would be to use itertools.groupby.

import itertools

list1 = [1, 2, 3, 3, 4, 3, 5, 5]
list1 = [g for g, _ in itertools.groupby(list1)]
print(list1)

outputs

[1, 2, 3, 4, 3, 5]

Method 5

You can do this by using zip_longest() + list comprehension.

from itertools import zip_longest 
list1 = [1, 2, 3, 3, 4, 3, 5, 5].
     # using zip_longest()+ list comprehension       
     res = [i for i, j in zip_longest(list1, list1[1:]) 
                                                            if i != j] 
        print ("List after removing consecutive duplicates : " +  str(res))

Method 6

Here is a solution without dependence on outside packages:

list = [1,1,1,1,1,1,2,3,4,4,5,1,2] 
L = list + [999]  # append a unique dummy element to properly handle -1 index
[l for i, l in enumerate(L) if l != L[i - 1]][:-1] # drop the dummy element

Then I noted that Ulf Aslak’s similar solution is cleaner 🙂

Method 7

To Eliminate consecutive duplicates of list elements; as an alternative, you may use itertools.zip_longest() with list comprehension as:

>>> from itertools import zip_longest

>>> my_list = [1,1,1,1,1,1,2,3,4,4,5,1,2]
>>> [i for i, j in zip_longest(my_list, my_list[1:]) if i!=j]
[1, 2, 3, 4, 5, 1, 2]

Method 8

Plenty of better/more pythonic answers above, however one could also accomplish this task using list.pop():

my_list = [1, 2, 3, 3, 4, 3, 5, 5]
for x in my_list[:-1]:
    next_index = my_list.index(x) + 1
    if my_list[next_index] == x:
        my_list.pop(next_index)

outputs

[1, 2, 3, 4, 3, 5]

Method 9

Another possible one-liner, using functools.reduce (excluding the import) – with the downside that string and list require slightly different implementations:

>>> from functools import reduce

>>> reduce(lambda a, b: a if a[-1:] == [b] else a + [b], [1,1,2,3,4,4,5,1,2], [])
[1, 2, 3, 4, 5, 1, 2]

>>> reduce(lambda a, b: a if a[-1:] == b else a+b, 'aa  bbb cc')
'a b c'


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x