Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is a Pythonic way to remove doubled duplicates in a list but allow triplets/greater?

Tags:

python

list

I have a list in Python

list1 = [0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1]

There are "groupings" of consecutive 1's and 0's. For my purposes, I am only interested in the consecutive 1's. Let's say if there is a solitary 1, e.g.

 ... 0, 0, 1, 0, 0 ...

I would like it to be changed into a 0. Similarly, if there are only pairs of 1's, these should become 0s as well. e.g.

.... 0, 0, 1, 1, 0, 0...

should become

.... 0, 0, 0, 0, 0, 0...

But "triplets" of consecutive ones or higher are ok.

I considered keeping track of the counts of 1s via a dictionary, but this feels too complex. The idea would be to iterate through the list, keeping track of the count of consecutive 1s in a list. But, how do you "go back" and switch the 1s to 0s?

counter_list = []
for i in list1: 
    if i == 1:
        counter_list = counter_list + 1
            if len(counter_list)==1 or len(counter_list)==2:
                # now I don't know how to "go back" to change these elements into 0s
like image 508
ShanZhengYang Avatar asked Mar 29 '17 21:03

ShanZhengYang


People also ask

How do I remove duplicate triplets from a list in Python?

Method #1 : Using sorted() + set() This particular problem can be solved using the above functions. The idea here is to sort the sublist and then remove the like elements using the set operations which removes duplicates.

How HashSet remove duplicates from a list?

Set implementations in Java has only unique elements. Therefore, it can be used to remove duplicate elements. HashSet<Integer>set = new HashSet<Integer>(list1); List<Integer>list2 = new ArrayList<Integer>(set); Above, the list2 will now have only unique elements.


3 Answers

This is an erosion followed by a dilation, common operations in computer vision:

>>> from scipy.ndimage.morphology import binary_dilation, binary_erosion
>>> print(list1)
[0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1]
>>> print(binary_dilation(binary_erosion(list1)).astype(int))
[0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1]

The composition of the two operations is called an opening:

>>> from scipy.ndimage.morphology import binary_opening
>>> print(binary_opening(list1).astype(int))
[0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1]
like image 162
wim Avatar answered Sep 28 '22 17:09

wim


You can use methods from image processing for this. The morphological operation "opening" with the structure element [1 1 1]should do the job. Should be a 1-liner.

like image 28
yar Avatar answered Sep 28 '22 16:09

yar


itertools.groupby can help by grouping the list into runs of 0s or 1s. From there, we can use the length of a group of 1s to decide whether to switch it to 0s, and use itertools.chain.from_iterable to fuse the groups back into one stream:

import itertools

groups = ((key, list(group)) for key, group in itertools.groupby(list1))

fixed_groups = (group if key==0 or len(group)>2 else [0]*len(group)
                for key, group in groups)

result = list(itertools.chain.from_iterable(fixed_groups))
like image 29
user2357112 supports Monica Avatar answered Sep 28 '22 15:09

user2357112 supports Monica