'Specify the consecutive values (zeros) and remove them but only if they are consecutive

I have this list of values:

A = [0,0,1,2,3,4,5,6,0,6,6,8,8,0,0,2,3,4,5,12,45,-0,-0,-9,-2,3,-0,-2,-2,-2]

I want to get this list of values for the output :

A = [1,2,3,4,5,6,0,6,6,8,8,2,3,4,5,12,45,-9,-2,3,-0,-2,-2,-2]

Basically, I want to drop the consecutive zeros only, and keep all the other values.

Do you have any idea on how i can do that ? I tried this one but i know there will be in index error :

X = []
for j in range(len(A)):
    if A[j] != 0 and A[j+1] != 0:
        X.append(A[j])
    else:
        print('lol')
print(X)```


Solution 1:[1]

You can use itertools.groupby and itertools.chain:

from itertools import groupby, chain

out = list(chain.from_iterable(G for k,g in groupby(A)
                               if len(G:=list(g))<2 or k!=0))

Explanation:

groupby will group the consecutive values. For each group, if the length is no more than 1 or the key (=value) is not 0, keep it. Finally chain all the groups together and convert to list.

Note that groupby returns iterators so I am using an assignment expression to perform the conversion.

output:

[1, 2, 3, 4, 5, 6, 0, 6, 6, 8, 8, 2, 3, 4, 5, 12, 45, -9, -2, 3, 0, -2, -2, -2]

Solution 2:[2]

With itertools:

from itertools import groupby

X = [x
     for x, [*xs] in groupby(A)
     if x or len(xs) == 1
     for x in xs]

Alternatively:

X = []
for x, [*xs] in groupby(A):
    if x or len(xs) == 1:
        X += xs        

Or taking any x that's not zero or where the previous and next values are not zero (padding with 1):

X = [x
     for p, x, n in zip([1]+A, A, A[1:]+[1])
     if x or p and n]

Solution 3:[3]

if u dont want to import itertools and prefer list comprehension

A = [i for index,i in enumerate(A) if i!=0 or index not in [0,len(A)] and A[index-1]!=i and A[index+1]!=i ]

note that this expressions uses the precedence of and operator over or operator

enumerate is used too

Solution 4:[4]

Here's a more simple, easy, and bit lengthy than other answers method to solve your problem

A = [0,0,1,2,3,4,5,6,0,6,6,8,8,0,0,2,3,4,5,12,45,-0,-0,-9,-2,3,-0,-2,-2,-2]
ind=[i for i,j in enumerate(A) if j==0]
C=[(ind[i],ind[i+1]) for i in range(len(ind)-1) if ind[i]+1==ind[i+1]]
D=[i for i1 in C for i in i1]
E=["" if i in D else j for i,j in enumerate(A)]
F=[i for i in E if i!=""]

# TEST
d_output=[1,2,3,4,5,6,0,6,6,8,8,2,3,4,5,12,45,-9,-2,3,-0,-2,-2,-2]
print(F==d_output)

Output: 1 i.e Your desired output

If you want to specify the value, then you can wrap it up in a function as below:

def remove_c(list_2,val):
    ind=[i for i,j in enumerate(list_2) if j==val]
    C=[(ind[i],ind[i+1]) for i in range(len(ind)-1) if ind[i]+1==ind[i+1]]
    D=[i for i1 in C for i in i1]
    E=["" if i in D else j for i,j in enumerate(A)]
    return [i for i in E if i!=""]
print(remove_c(A,10))

Explantion:

  1. I have taken all the indexes of 0 in the list.
  2. Checked if the indexes are consecutive or not. If they are, then append them in the list C in tuple.
  3. And, because the list C contains tuple, created a flat list D out of list C.
  4. Replaced the indexes of list D with "".
  5. Removed "" for the list. I have noticed a silly mistake in your code:
X = []
for j in range(len(A)): # Mistake here
    if A[j] != 0 and A[j+1] != 0: # if we bypassed the above error we can also get error here
        X.append(A[j])
    else:
        print('lol')
print(X)

The problem is when the i is at last index of the list, there would be no other index but you have hard-coded to search for index+1, so it would throw an error.

There are 2 method to solve this:

  • Use try and except.
  • Replace range(len(A) to range(len(A)-1).

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 mozway
Solution 2
Solution 3
Solution 4