Ich habe eine Herausforderung in JavaScript, die ich bereits seit einiger Zeit herausfinden möchte.
Betrachten Sie dieses Array:
let arr = [0, 1, 0, 2, 0, 3, 0, 4, 0, 5];
Ich muss dieses Ergebnis ausgeben:
arr = [0, 0, 0, 0, 0, 5, 4, 3, 2, 1]
Ich folge dieser Logik, um die Nullen vorne zu positionieren und den Indexwert anzupassen:
arr.sort((x, y) => {
if (x !== 0) {
return 1;
}
if (x === 0) {
return -1;
}
return y - x;
});
Aber ich stecke bei diesem Ergebnis fest:
arr = [0, 0, 0, 0, 0, 1, 2, 3, 4, 5]
Hat jemand irgendwelche Tipps, wie man das löst?
javascript
arrays
sorting
lianbwl
quelle
quelle
return x - y;
?return y - x;
? Selbst in Javascript fällt mir nichts ein, was weder===0
noch wäre!==0
.Antworten:
Sie können nach dem Delta von
b
unda
(für absteigende Sortierung) sortieren undNumber.MAX_VALUE
für falsche Werte wie Null nehmen.Diese:
ist gleich Null.
quelle
NaN
wenn beidea
undb
Null sind. Dies kann unerwünschtes Verhalten sein.Array.prototype.sort
sind implementierungsdefiniert, falls der Komparator jemals zurückkehrtNaN
. Daher ist dieser Komparator eine schlechte Idee. Es versucht klug zu sein und macht es falsch.Wie mdn docs sagt:
Wenn a und b zwei Elemente sind, die verglichen werden, dann:
Die Vergleichsfunktion hat also die folgende Form:
quelle
Wenn Sie Wert auf Effizienz legen, ist es wahrscheinlich am schnellsten, zuerst die Nullen herauszufiltern . Sie möchten keine
sort
Zeit damit verschwenden, sie sich anzusehen, geschweige denn Ihrem Vergleichsrückruf zusätzliche Arbeit hinzuzufügen, um diesen Sonderfall zu behandeln.Insbesondere wenn Sie eine signifikante Anzahl von Nullen erwarten, sollte ein Durchlauf über die Daten zum Herausfiltern viel besser sein als eine größere O (N log N) -Sortierung, bei der jede Null mehrmals betrachtet wird.
Sie können die richtige Anzahl von Nullen effizient voranstellen, nachdem Sie fertig sind.
Genauso einfach ist es, den resultierenden Code zu lesen. Ich habe TypedArray verwendet, weil es effizient ist und das numerische Sortieren vereinfacht . Sie können diese Technik jedoch mit regulären Arrays verwenden, wobei Sie die Standardsprache
(a,b)=>a-b
for verwenden.sort
.Ich weiß nicht, ob TypedArray
.sort()
und dann.reverse
schneller als die Verwendung einer benutzerdefinierten Vergleichsfunktion zum Sortieren in absteigender Reihenfolge. Oder wenn wir mit einem Iterator im laufenden Betrieb kopieren und umkehren können.Ebenfalls erwägenswert: Verwenden Sie nur ein TypedArray in voller Länge .
Anstatt zu verwenden
.filter
, schleifen Sie darüber und tauschen Sie die Nullen an die Vorderseite des Arrays, während Sie fortfahren. Dies dauert einen Durchgang über Ihre Daten.Verwenden Sie dann
.subarray()
, um eine neue TypedArray-Ansicht der Nicht-Null-Elemente desselben zugrunde liegenden ArrayBuffers abzurufen. Durch die Sortierung erhalten Sie das gesamte Array mit einem Nullstart und einem sortierten Ende, wobei die Sortierung immer nur die Nicht-Null-Elemente betrachtet.Ich habe keine Partitionsfunktion in den Array- oder TypedArray-Methoden gesehen, kenne aber kaum JavaScript. Mit einer guten JIT sollte eine Schleife nicht zu viel schlechter sein als eine integrierte Methode. (Insbesondere wenn diese Methode einen Rückruf wie beinhaltet
.filter
und nichtrealloc
unter der Haube zum Verkleinern verwendet wird, muss sie herausfinden, wie viel Speicher zugewiesen werden muss, bevor sie tatsächlich gefiltert wird.)Ich habe
.filter()
vor der Konvertierung in ein TypedArray ein reguläres Array verwendet. Wenn Ihre Eingabe bereits ein TypedArray ist, haben Sie dieses Problem nicht und diese Strategie wird noch attraktiver.quelle
Ändern Sie einfach den Zustand Ihrer Vergleichsfunktion wie folgt:
quelle
!a
immer noch wahr. Es wird zurückkehren-1
a=b=0
Hier kein Code Golf spielen:
quelle
Schreiben Sie keine eigene numerische Sortierung, wenn diese bereits vorhanden ist. Was Sie tun möchten, ist genau das, was Sie im Titel sagen. Sortieren Sie die Nummern in absteigender Reihenfolge mit Ausnahme von Nullen am Anfang.
Schreiben Sie keinen Code, den Sie nicht benötigen. Sie könnten es falsch verstehen.
Wählen Sie das TypedArray basierend auf dem Typ der Zahlen aus, die das Array verarbeiten soll. Float64 ist eine gute Standardeinstellung, da alle normalen JS-Nummern verarbeitet werden.
quelle
Array(n).fill(0)
.let f64arr = new Float64Array(arr.filter(n => n != 0))
dann tun[ ...Array(arr.length - f64arr.length).fill(0),
... also fügt es 1 zusätzliche Zeile hinzu und vereinfacht die letzte Zeile.Sie können dies folgendermaßen tun:
oder Sie können dies tun:
quelle
quelle