I will try to explain my issue with simple example. Let's say I've a list
lis = ['Elemnt-1' , 'Elemnt-2' , 'Elemnt-3' , '' , '' , 'Elemnt-6' , 'Elemnt-7']
How can I fill this missing values such that list will become.
lis = ['Elemnt-1' , 'Elemnt-2' , 'Elemnt-3' , 'Elemnt-2' , 'Elemnt-3' , 'Elemnt-6' , 'Elemnt-7']
Explination with similar animation.
I've figured out solution. Which is too inefficient for a longer lists & when I've multiple missing values. Here is my logic
from itertools import accumulate
lis = ['Elemnt-1' , 'Elemnt-2' , 'Elemnt-3' , '' , '' , 'Elemnt-6' , 'Elemnt-7']
odd_index = lis[::2]
even_index = lis[1::2]
odd_index = list(accumulate(odd_index,lambda x, y: x if y is '' else y))
even_index = list(accumulate(even_index,lambda x, y: x if y is '' else y))
zipper = list(sum(zip(odd_index, even_index [0]), ())[:-1])
print(zipper)
Given me #
['Elemnt-1', 'Elemnt-2', 'Elemnt-3', 'Elemnt-2', 'Elemnt-3', 'Elemnt-6', 'Elemnt-7']
I was looking for a simpler elegant approach to solve this when there are multiple missing values in middle of list.
More examples:
lis = ['Elemnt-1' , 'Elemnt-2' , 'Elemnt-3' , '' , '' , '' , 'Elemnt-7']
Need
lis = ['Elemnt-1' , 'Elemnt-2' , 'Elemnt-3' , 'Elemnt-1' , 'Elemnt-2' , 'Elemnt-3' , 'Elemnt-7']
Another example
lis = ['Elemnt-1' , 'Elemnt-2' , 'Elemnt-3' , '' , '' , 'Elemnt-6' , 'Elemnt-7', '']
Need
lis = ['Elemnt-1' , 'Elemnt-2' , 'Elemnt-3' , 'Elemnt-2' , 'Elemnt-3' , 'Elemnt-6' , 'Elemnt-7' , 'Elemnt-7']
Logically n blank elements should be filled with n back elements
CodePudding user response:
If the missing values are consecutive ones as you showed in the example you can use this.
def fillList(list):
emptyCount = list.count('')
for item in list:
if item == '':
list[list.index(item)] = list[list.index(item) - emptyCount]
return list
CodePudding user response:
Using a list comprehension to replace empty values with value of this list two positions before. Repeats until no empty values left.
EDIT : after comments, it appears that it is not always 2 position before, but n blank elements should be filled with n elements before. Answer therefore is still missing something. Replacing lis[index-2]
by lis[index-lis.count('')]
would not work because it is possible to have multiple set of empty spaces
filler = ['']*len(lis)
while '' in lis :
filler = [lis[index-2] if value=="" else value for index, value in enumerate(lis)]
print(filler)
lis=filler
print(lis)
CodePudding user response:
Because you're looking 2 back to fill the empty spots, we skip the first 2 indeces as there's nothing before theme. Here I define a func that does this:
def filler(l: list):
for i in range(2, len(l)):
if l[i] == '':
l[i] = l[i-2]
return l
print(filler(['Elemnt-1' , 'Elemnt-2' , 'Elemnt-3' , '' , '' , 'Elemnt-6' , 'Elemnt-7']))
Out:
['Elemnt-1', 'Elemnt-2', 'Elemnt-3', 'Elemnt-2', 'Elemnt-3', 'Elemnt-6', 'Elemnt-7']
CodePudding user response:
You can determine the blank ranges first, then fill them with the previous items.
lst = ['Elment-1' , 'Elment-2' , 'Elment-3' , '' , '' , 'Elment-6' , 'Elment-7', '']
lst_ext = ['p'] lst ['p']
# boundary of all blank ranges
blank_bound = [idx for idx, (a, b) in enumerate(zip(lst_ext, lst_ext[1:])) \
if (a == '' or b == '') and a != b] # [3, 5, 7, 8]
# fill each blank range
for l, r in zip(blank_bound[::2], blank_bound[1::2]):
assert 2*l-r >= 0, "no enough items before the blank item"
lst[l:r] = lst[2*l-r:l]