Is it possible to fill up zero values with arange without iterations:
Initial array:
array([128, 0, 128, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0,
0, 0, 128, 128, 0, 0, 128, 128, 128, 0, 0, 0, 0,
0, 0, 0, 128, 0, 0, 0, 0, 0, 128, 0, 0, 128,
128, 0, 0, 128, 0, 0, 0, 128, 0, 0, 128, 128, 0,
0, 0, 128, 128], dtype=uint8)
new array:
array([128, 0, 128, 0, 1, 2, 128, 0, 1, 2, 3, 4, 5,
6, 7, 128, 128, 0, 1, 128, 128, 128, 0, 1, 2, 3,
4, 5, 6, 128, 0, 1, 2, 3, 4, 128, 0, 1, 128,
128, 0, 1, 128, 0, 1, 2, 128, 0, 1, 128, 128, 0,
1, 2, 128, 128], dtype=uint8)
CodePudding user response:
This works:
zeros = a == 0
idxs = np.arange(len(a))
zero_block_starts = np.diff(zeros, prepend = 0) == 1
ranges = idxs - np.maximum.accumulate(zero_block_starts * idxs)
result = a.copy()
result[zeros] = ranges[zeros]
Result:
>>> a
array([128, 0, 128, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0,
0, 0, 128, 128, 0, 0, 128, 128, 128, 0, 0, 0, 0,
0, 0, 0, 128, 0, 0, 0, 0, 0, 128, 0, 0, 128,
128, 0, 0, 128, 0, 0, 0, 128, 0, 0, 128, 128, 0,
0, 0, 128, 128], dtype=uint8)
>>> result
array([128, 0, 128, 0, 1, 2, 128, 0, 1, 2, 3, 4, 5,
6, 7, 128, 128, 0, 1, 128, 128, 128, 0, 1, 2, 3,
4, 5, 6, 128, 0, 1, 2, 3, 4, 128, 0, 1, 128,
128, 0, 1, 128, 0, 1, 2, 128, 0, 1, 128, 128, 0,
1, 2, 128, 128], dtype=uint8)
I'd be wary to use this one a uint8
dtype array though, as gaps larger than 256 elements will overflow.
CodePudding user response:
I tried to do it recursively
def rec_fill_zero(init_list, index, zero_count):
if init_list[index] == 128:
head = 128
next_zero_count = 0
else:
head = zero_count
next_zero_count = zero_count 1
if init_list.size - index > 1:
init_list[index] = head
rec_fill_zero(init_list, index 1, next_zero_count)
def fill_zero(initial_array):
new_array = initial_array.copy()
rec_fill_zero(new_array, 0, 0)
return new_array
Result:
>>> initial_array
array([128, 0, 128, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0,
0, 0, 128, 128, 0, 0, 128, 128, 128, 0, 0, 0, 0,
0, 0, 0, 128, 0, 0, 0, 0, 0, 128, 0, 0, 128,
128, 0, 0, 128, 0, 0, 0, 128, 0, 0, 128, 128, 0,
0, 0, 128, 128], dtype=uint8)
>>> fill_zero(initial_array)
array([128, 0, 128, 0, 1, 2, 128, 0, 1, 2, 3, 4, 5,
6, 7, 128, 128, 0, 1, 128, 128, 128, 0, 1, 2, 3,
4, 5, 6, 128, 0, 1, 2, 3, 4, 128, 0, 1, 128,
128, 0, 1, 128, 0, 1, 2, 128, 0, 1, 128, 128, 0,
1, 2, 128, 128], dtype=uint8)