Angenommen, ich habe ein NumPy-Array:
x = np.array([0, 1, 2, 0, 4, 5, 6, 7, 0, 0])
Bei jedem Index möchte ich den Abstand zum nächsten Nullwert ermitteln. Wenn die Position selbst eine Null ist, geben Sie als Abstand Null zurück. Danach interessieren uns nur noch Entfernungen zur nächsten Null rechts von der aktuellen Position. Der super naive Ansatz wäre so etwas wie:
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
Und die Ausgabe wäre:
array([0, 2, 1, 0, 4, 3, 2, 1, 0, 0])
Ich bemerke ein Countdown- / Dekrementmuster in der Ausgabe zwischen den Nullen. Ich könnte also in der Lage sein, die Positionen der Nullen zu verwenden (dh zero_indices = np.argwhere(x == 0).flatten()
)
Was ist der schnellste Weg, um die gewünschte Ausgabe in linearer Zeit zu erhalten?
x.shape[0] - 1
) verwendet werdenAntworten:
Ansatz Nr. 1:
Searchsorted
Zur vektorisierten Rettung der linearen Zeit (bevor Numba-Typen hereinkommen)!Ansatz Nr. 2: Ein anderer mit einigen
cumsum
-Alternativ könnte der letzte Schritt von
cumsum
durchrepeat
Funktionalität ersetzt werden -Ansatz Nr. 3: Ein anderer mit meist nur
cumsum
-quelle
Sie könnten von der anderen Seite arbeiten. Behalten Sie einen Zähler für die Anzahl der Ziffern ungleich Null bei und weisen Sie ihn dem Element im Array zu. Wenn Sie 0 sehen, setzen Sie den Zähler auf 0 zurück
Bearbeiten: Wenn rechts keine Null steht, benötigen Sie eine weitere Prüfung
quelle
Sie können die Differenz zwischen den Indizes jeder Position und dem kumulierten Maximum von Nullpositionen verwenden, um den Abstand zur vorhergehenden Null zu bestimmen. Dies kann vorwärts und rückwärts erfolgen. Der Mindestabstand zwischen Vorwärts- und Rückwärtsabstand zur vorhergehenden (oder nächsten) Null ist der nächste:
Ergebnisse:
Sonderfall, bei dem an den Außenkanten keine Nullen vorhanden sind:
funktioniert auch ohne Nullen
[EDIT] nicht numpy Lösungen ...
Wenn Sie nach einer O (N) -Lösung suchen, für die kein Numpy erforderlich ist, können Sie diese Strategie mithilfe der Akkumulationsfunktion von itertools anwenden:
Ausgabe:
Wenn Sie keine Bibliothek verwenden möchten, können Sie die Entfernungen manuell in einer Schleife akkumulieren:
Ausgabe:
quelle
Meine erste Intuition wäre das Schneiden. Wenn x eine normale Liste anstelle eines numpy-Arrays sein kann, können Sie verwenden
Wenn numpy notwendig ist, können Sie verwenden
Dies ist jedoch weniger effizient, da Sie alle Nullstellen rechts vom Wert finden und dann nur die erste herausziehen. Fast definitiv ein besserer Weg, dies in Numpy zu tun.
quelle
Edit: Es tut mir leid, ich habe falsch verstanden. Dies gibt Ihnen den Abstand zu den nächsten Nullen - kann es links oder rechts sein. Sie können aber
d_right
als Zwischenergebnis verwenden. Dies gilt jedoch nicht für den Randfall, dass rechts keine Null steht.quelle