this is an example list:
mylist = [0,0,1,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,1,0,0,1]
I need to search the list for adjacent 0 until no zeros are adjacent. My needed output-
newlist = [0,x,1,0,1,0,x,x,1,0,x,x,x,1,0,x,x,1,0,1,0,x,1]
so I retain a single zero at its correct index, but replace its adjacents with "x". I am new to python and have take some very unsuccessful stabs at it.
I tried creating a while loop but I'm sad cuz bad.
CodePudding user response:
Zip the list together with a lagged copy of itself and use a list comprehension to produce the new list:
newlist = ["x" if a == b == 0 else b for a, b in zip([None] mylist, mylist)]
I understood from your question that you are only looking for duplicate zeroes. But if you want to replace all duplicates, just remove the == 0
:
newlist = ["x" if a == b else b for a, b in zip([None] mylist, mylist)]
CodePudding user response:
You can achieve this using itertools.groupby()
:
from itertools import groupby
mylist = [0,0,1,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,1,0,0,1]
new_list = []
for _, j in groupby(mylist):
new_list.append(next(j))
for _ in j:
new_list.append('x')
# which will return you `new_list` as:
# [0, 'x', 1, 0, 1, 0, 'x', 'x', 1, 0, 'x', 'x', 'x', 1, 0, 'x', 'x', 1, 0, 1, 0, 'x', 1]
Here's an one liner to achieve this with additional usage of itertools.chain.from_iterable()
:
from itertools import groupby, chain
new_list = list(chain.from_iterable((next(j), *['x' for _ in j]) for _, j in groupby(mylist)))
# which will return you `new_list` as:
# [0, 'x', 1, 0, 1, 0, 'x', 'x', 1, 0, 'x', 'x', 'x', 1, 0, 'x', 'x', 1, 0, 1, 0, 'x', 1]
CodePudding user response:
This is likely the most simple and efficient solution. Using the walrus operator to assign the last number seen during iteration in a comprehension.
my_list = [0,0,1,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,1,0,0,1]
last = None
output = ['x' if last == n else (last := n) for n in my_list]
Output:
[0, 'x', 1, 0, 1, 0, 'x', 'x', 1, 0, 'x', 'x', 'x', 1, 0, 'x', 'x', 1, 0, 1, 0, 'x', 1]