492 Stimmen

Wie kann man ein Array sortieren, ohne das ursprüngliche Array zu verändern?

Nehmen wir an, ich wollte eine Sortierfunktion, die eine sortierte Kopie des eingegebenen Arrays zurückgibt. Ich habe naiverweise Folgendes versucht

function sort(arr) {
  return arr.sort();
}

und ich habe es damit getestet, was zeigt, dass meine sort Methode verändert das Array.

var a = [2,3,7,5,3,7,1,3,4];
sort(a);
alert(a);  //alerts "1,2,3,3,3,4,5,7,7"

Ich habe auch diesen Ansatz ausprobiert

function sort(arr) {
  return Array.prototype.sort(arr);
}

aber es funktioniert überhaupt nicht.

Gibt es eine einfache Möglichkeit, um dies zu umgehen, vorzugsweise ein Weg, der nicht Hand-Rolling meine eigenen Sortieralgorithmus oder Kopieren jedes Element des Arrays in eine neue erfordert?

1 Stimmen

Eine tiefe Kopie des Arrays erstellen und es stattdessen sortieren.

2 Stimmen

@evanmcdonnal Eine flache Kopie könnte ausreichen, wenn alles, was gewünscht ist, ist eine Neuordnung und nicht ein Duplikat von jedem Element in dem Array.

0 Stimmen

.sort erfordert die this Wert das Array sein. Damit das letzte Snippet funktioniert, müssen Sie also .sort.call(arr) (obwohl das Ihr Problem nicht löst).

18voto

Ran Turner Punkte 8004

Update - Array.prototype.toSorted() Vorschlag

En Array.prototype.toSorted(compareFn) -> Array ist eine Methode, die vorgeschlagen wurde, um die Array.prototype und befindet sich derzeit in Stufe 3 (Demnächst verfügbar).

Diese Methode lässt das Ziel-Array unangetastet und gibt stattdessen eine Kopie davon zurück, in der die Änderung vorgenommen wurde.

4voto

Prati Punkte 9

Versuchen Sie dies, um die Zahlen zu sortieren. Dabei wird das ursprüngliche Array nicht verändert.

function sort(arr) {
  return arr.slice(0).sort((a,b) => a-b);
}

2voto

Hamada Punkte 37

Jeder, der eine tiefe Kopie durchführen möchte (z.B. wenn Ihr Array Objekte enthält), kann dies tun:

let arrCopy = JSON.parse(JSON.stringify(arr))

Dann können Sie sortieren arrCopy ohne Veränderung arr .

arrCopy.sort((obj1, obj2) => obj1.id > obj2.id)

Bitte beachten Sie, dass dies bei sehr großen Arrays langsam sein kann.

1 Stimmen

Dies funktioniert mit - anstelle von > in Ihrem zweiten Beispiel.

2 Stimmen

Und denken Sie daran, dass alle Ihre Elemente serialisierbar sein sollten, um sie nach der Stringifizierung zurückzubringen (z. B. Datumsobjekte, Funktionen und Symbole sind bei dieser Methode problematisch)

2voto

Josh Punkte 1776

Es gibt eine neue tc39 Vorschlag , die eine toSorted Methode zu Array die eine Kopie des Arrays zurückgibt und das Original nicht verändert.

Zum Beispiel:

const sequence = [3, 2, 1];
sequence.toSorted(); // => [1, 2, 3]
sequence; // => [3, 2, 1]

Da es sich derzeit in Phase 3 befindet, wird es wahrscheinlich bald in Browser-Engines implementiert werden, aber in der Zwischenzeit ist ein Polyfill verfügbar aquí oder in core-js .

0voto

Oleh Dzoba Punkte 1

Ich denke, dass meine Antwort ein bisschen zu spät kommt, aber wenn jemand wieder auf dieses Problem stößt, könnte die Lösung nützlich sein.

Ich kann noch einen anderen Ansatz vorschlagen, und zwar eine native Funktion, die gibt ein sortiertes Array zurück .

Dieser Code mutiert immer noch das ursprüngliche Objekt, aber anstelle des nativen Verhaltens gibt diese Implementierung ein sortiertes Array zurück.

// Remember that it is not recommended to extend build-in prototypes 
// or even worse override native functions.  
// You can create a seperate function if you like

// You can specify any name instead of "sorted" (Python-like)

// Check for existence of the method in prototype
if (typeof Array.prototype.sorted == "undefined") {
  // If it does not exist you provide your own method
  Array.prototype.sorted = function () {
    Array.prototype.sort.apply(this, arguments);
    return this;
  };
}

Diese Art der Problemlösung war in meiner Situation ideal.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X