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
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.
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.
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]
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.
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))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With