Digamos que eu tenho uma matriz NumPy:
x = np.array([0, 1, 2, 0, 4, 5, 6, 7, 0, 0])
Em cada índice, quero encontrar a distância para o valor zero mais próximo. Se a posição for um zero, retorne zero como uma distância. Posteriormente, estamos interessados apenas nas distâncias até o zero mais próximo, à direita da posição atual. A abordagem super ingênua seria algo como:
out = np.full(x.shape[0], x.shape[0]-1)
for i in range(x.shape[0]):
j = 0
while i + j < x.shape[0]:
if x[i+j] == 0:
break
j += 1
out[i] = j
E a saída seria:
array([0, 2, 1, 0, 4, 3, 2, 1, 0, 0])
Estou percebendo um padrão de contagem regressiva / decréscimo na saída entre os zeros. Então, eu posso usar os locais dos zeros (ou seja, zero_indices = np.argwhere(x == 0).flatten()
)
Qual é a maneira mais rápida de obter a saída desejada em tempo linear?
x.shape[0] - 1
))Respostas:
Abordagem 1:
Searchsorted
resgatar o tempo linear de maneira vetorizada (antes que os numba entrem)!Abordagem # 2: Outra com alguns
cumsum
-Como alternativa, o último passo
cumsum
pode ser substituído pelarepeat
funcionalidade -Abordagem # 3: outra com principalmente apenas
cumsum
-fonte
Você poderia trabalhar do outro lado. Mantenha um contador de quantos dígitos diferentes de zero passaram e atribua-o ao elemento na matriz. Se você vir 0, redefina o contador para 0
Editar: se não houver zero à direita, você precisará de outra verificação
fonte
Você pode usar a diferença entre os índices de cada posição e o máximo cumulativo de posições zero para determinar a distância até o zero anterior. Isso pode ser feito para frente e para trás. O mínimo entre a distância de avanço e retrocesso até o zero anterior (ou próximo) será o mais próximo:
resultados:
Caso especial em que não há zeros nas bordas externas:
também funciona sem zeros
[EDIT] soluções não-numpy ...
se você estiver procurando por uma solução O (N) que não exija numpy, aplique esta estratégia usando a função acumular do itertools:
resultado:
Se você não quiser usar nenhuma biblioteca, poderá acumular as distâncias manualmente em um loop:
resultado:
fonte
Minha primeira intuição seria usar a fatia. Se x puder ser uma lista normal em vez de uma matriz numpy, você poderá usar
se for necessário um numpy, você pode usar
mas isso é menos eficiente, porque você encontra todos os zero locais à direita do valor e, em seguida, extrai apenas o primeiro. Definitivamente, é a melhor maneira de fazer isso em um meio confuso.
fonte
Edit: Me desculpe, eu entendi errado. Isso lhe dará a distância para os zeros mais próximos - seja à esquerda ou à direita. Mas você pode usar
d_right
como resultado intermediário. Isso não cobre o caso extremo de não ter zero à direita.fonte