Home > Software engineering >  Fill up contiguous sequences of zeros with incrementing sequences
Fill up contiguous sequences of zeros with incrementing sequences

Time:11-30

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)
  • Related