Disons que j'ai un tableau NumPy:
x = np.array([0, 1, 2, 0, 4, 5, 6, 7, 0, 0])
À chaque index, je veux trouver la distance à la valeur zéro la plus proche. Si la position est un zéro lui-même, retournez zéro comme distance. Par la suite, nous nous intéressons uniquement aux distances au zéro le plus proche situé à droite de la position actuelle. L'approche super naïve serait quelque chose comme:
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
Et la sortie serait:
array([0, 2, 1, 0, 4, 3, 2, 1, 0, 0])
Je remarque un schéma de compte à rebours / décrément dans la sortie entre les zéros. Donc, je pourrais peut-être utiliser les emplacements des zéros (c.-à-d. zero_indices = np.argwhere(x == 0).flatten()
)
Quel est le moyen le plus rapide d'obtenir la sortie souhaitée en temps linéaire?
x.shape[0] - 1
)Réponses:
Approche n ° 1:
Searchsorted
à la rescousse du temps linéaire de manière vectorisée (avant que les gars de Numba n'entrent)!Approche n ° 2: une autre avec certains
cumsum
-Alternativement, la dernière étape de
cumsum
pourrait être remplacée par desrepeat
fonctionnalités -Approche n ° 3: une autre avec surtout juste
cumsum
-la source
Vous pourriez travailler de l'autre côté. Gardez un compteur sur le nombre de chiffres non nuls passés et affectez-le à l'élément du tableau. Si vous voyez 0, remettez le compteur à 0
Edit: s'il n'y a pas de zéro à droite, alors vous avez besoin d'un autre contrôle
la source
Vous pouvez utiliser la différence entre les indices de chaque position et le maximum cumulé des positions nulles pour déterminer la distance au zéro précédent. Cela peut être fait en avant et en arrière. La distance minimale entre l'avant et l'arrière au zéro précédent (ou suivant) sera la plus proche:
résultats:
Cas particulier où aucun zéro n'est présent sur les bords extérieurs:
fonctionne également sans aucun zéro
[EDIT] solutions non numpy ...
si vous recherchez une solution O (N) qui ne nécessite pas numpy, vous pouvez appliquer cette stratégie en utilisant la fonction d'accumulation d'itertools:
production:
Si vous ne souhaitez utiliser aucune bibliothèque, vous pouvez accumuler les distances manuellement dans une boucle:
production:
la source
Ma première intuition serait d'utiliser le tranchage. Si x peut être une liste normale au lieu d'un tableau numpy, alors vous pouvez utiliser
si numpy est nécessaire, vous pouvez utiliser
mais cela est moins efficace car vous recherchez tous les emplacements zéro à droite de la valeur, puis vous retirez uniquement le premier. Certainement une meilleure façon de le faire en numpy.
la source
Edit: je suis désolé, j'ai mal compris. Cela vous donnera la distance aux zéros les plus proches - que ce soit à gauche ou à droite. Mais vous pouvez utiliser
d_right
comme résultat intermédiaire. Cela ne couvre pas le cas de bord de ne pas avoir de zéro à droite.la source