Допустим, у меня есть массив NumPy:
x = np.array([0, 1, 2, 0, 4, 5, 6, 7, 0, 0])
В каждом индексе я хочу найти расстояние до ближайшего нулевого значения. Если позиция сама по себе равна нулю, верните ноль как расстояние. После этого нас интересуют только расстояния до ближайшего нуля, который находится справа от текущей позиции. Супер наивный подход будет что-то вроде:
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
И вывод будет:
array([0, 2, 1, 0, 4, 3, 2, 1, 0, 0])
Я замечаю схему обратного отсчета / уменьшения на выходе между нулями. Таким образом, я мог бы быть в состоянии использовать расположение нулей (т.е. zero_indices = np.argwhere(x == 0).flatten()
)
Какой самый быстрый способ получить желаемый результат за линейное время?
x.shape[0] - 1
Ответы:
Подход № 1:
Searchsorted
к спасению для линейного времени в векторизации (до того, как придут парни из Numba)!Подход № 2. Другой с некоторыми
cumsum
-Кроме того, последний шаг
cumsum
может быть замененrepeat
функциональностью -Подход № 3: Еще с главным образом только
cumsum
-источник
Вы могли бы работать с другой стороны. Держите счетчик на количество переданных ненулевых цифр и присвойте его элементу в массиве. Если вы видите 0, сбросьте счетчик на 0
Редактировать: если справа нет нуля, то вам нужна еще одна проверка
источник
Вы можете использовать разницу между индексами каждой позиции и совокупным максимумом нулевых позиций, чтобы определить расстояние до предыдущего нуля. Это может быть сделано вперед и назад. Минимум между прямым и обратным расстоянием до предыдущего (или следующего) нуля будет ближайшим:
Результаты:
Особый случай, когда на внешних ребрах нет нулей:
также работает без нулей вообще
[РЕДАКТИРОВАТЬ] non-numpy решения ...
если вы ищете решение O (N), которое не требует numpy, вы можете применить эту стратегию, используя функцию накопления из itertools:
вывод:
Если вы не хотите использовать какую-либо библиотеку, вы можете накапливать расстояния вручную в цикле:
вывод:
источник
Моей первой интуицией было бы использовать нарезку. Если x может быть обычным списком вместо массива, вы можете использовать
если нужна numpy, вы можете использовать
но это менее эффективно, потому что вы находите все нулевые позиции справа от значения, а затем вытаскиваете только первое. Почти наверняка лучший способ сделать это в NumPy.
источник
Изменить: я извиняюсь, я неправильно понял. Это даст вам расстояние до ближайших нулей - может ли оно быть слева или справа. Но вы можете использовать
d_right
как промежуточный результат. Это не охватывает крайний случай отсутствия нуля вправо.источник