Reputation: 83
I have a problem statement where i have to fill the missing values ("_") in a specified way.
Example
Input:- ",,30,,,,50,,_" Output:- 10,10,12,12,12,12,4,4,4
How it is getting filled? we will fill the missing values from left to right a. first we will distribute the 30 to left two missing values (10, 10, 10, _, _, _, 50, _, _) b. now distribute the sum (10+50) missing values in between (10, 10, 12, 12, 12, 12, 12, _, _) c. now we will distribute 12 to right side missing values (10, 10, 12, 12, 12, 12, 4, 4, 4)
My code is as below
s = "_,_,30,_,_,_,50,_,_"
s = s.split(",")
print(s)
print('***********')
result = []
count = s.index('30') + 1
print(count)
print('****************')
value = int(s[2]) / count
while count > 1:
result.append(str(int(value)))
count -= 1
value = int((value + int(s[6])) / (6 - 2 + 1))
count = 6 - 2 + 1
while count > 1:
result.append(str(value))
count -= 1
value = int(value / (len(s) - 6))
count = len(s) - 6
while count > 0:
result.append(str(value))
count -= 1
print(result)
Only problem is here i am making things hardcoded, so instead of 30/50 if there are any other numbers my code is not going to work. So can someone help me to fix this hard coded part.
Upvotes: 2
Views: 133
Reputation: 413
import copy
def is_int(num):
try:
int(num)
return True
except Exception as e:
return False
def fill_empty(d_list, start, end, avg):
for i in range(start, end+1):
d_list[i] = avg
return d_list
def get_starts(d_list):
start = d_list.index('_')
if start != 0:
before_value = int(d_list[start-1])
start -= 1
else:
before_value = 0
return start,before_value
def process():
s = '_,_,30,_,_,_,50,_,_'
s_list = s.split(",")
res_list = copy.copy(s_list)
for i in range(1, len(s_list)):
pre = s_list[i-1]
cur = s_list[i]
end = i
if pre == '_' and is_int(cur):
start,before_value = get_starts(res_list)
length = end-start+1
avg = (before_value + int(cur))/length
res_list = fill_empty(res_list, start, end, avg)
elif cur == '_' and i == len(s_list)-1:
start,before_value = get_starts(res_list)
length = end-start+1
avg = (before_value + 0)/length
res_list = fill_empty(res_list, start, end, avg)
return res_list
r = process()
print(r)
# [10.0, 10.0, 12.0, 12.0, 12.0, 12.0, 4.0, 4.0, 4.0]
Upvotes: 1
Reputation: 162
Try this recursive method.
MISSING = '_'
def settle(s):
water = [x if x == MISSING else float(x) for x in s.split(',')]
return settle_water(water)
def settle_water(water):
if MISSING not in water:
return water
i = 0
while i + 1 < len(water) and water[i + 1] != MISSING:
i += 1
j = i + 1
while j + 1 < len(water) and water[j] == MISSING:
j += 1
average = ((0 if water[i] == MISSING else water[i]) + (0 if water[j] == MISSING else water[j])) / (j - i + 1)
water[i : j + 1] = [average] * (j - i + 1)
return water[:j] + settle_water(water[j:])
assert settle('_,_,30,_,_,_,50,_,_') == [10,10,12,12,12,12,4,4,4]
assert settle('1,_,_,3,_') == [1,1,1,0.5,0.5]
Upvotes: 0
Reputation: 2405
First version, could be rough on corner cases
s = "_,_,30,_,_,_,50,_,_"
l = s.split(",")
out = []
last_pos = 0
for index, elem in enumerate(l):
if elem == "_":
if index == (len(l) - 1) and out:
elem_to_div = out[-1]
num = (index - last_pos + 1)
if out:
del out[-1]
fills = elem_to_div / num
out.extend([fills]*num)
continue
elem = int(elem)
num = (index - last_pos + 1)
elem_to_div = elem if not out else elem + out[-1]
fills = elem_to_div / num
if out:
del out[-1]
out.extend([fills]*num)
last_pos = index
Which outputs
>>> out
[10.0, 10.0, 12.0, 12.0, 12.0, 12.0, 4.0, 4.0, 4.0]
Upvotes: 1