Array in Javascript umkehren, ohne das ursprüngliche Array zu mutieren

187

Array.prototype.reverse kehrt den Inhalt eines Arrays um (mit Mutation) ...

Gibt es eine ähnlich einfache Strategie zum Umkehren eines Arrays, ohne den Inhalt des ursprünglichen Arrays zu ändern (ohne Mutation)?

sfletche
quelle
1
Mögliches Duplikat von
Erstellen
Hier ist ein Benchmark, der die verschiedenen Optionen vergleicht: jsben.ch/HZ7Zp
Solomon Ucko

Antworten:

372

Sie können Slice () verwenden , um eine Kopie zu erstellen, und diese dann umkehren ()

var newarray = array.slice().reverse();

Arun P Johny
quelle
Können Sie bitte Slice () ohne Parameter erklären?
Alex
3
@ Alex Slice - If begin is omitted, slice begins from index 0.- so ist es das gleiche wiearray.slice(0)
Arun P Johny
2
Ich denke, @Alex bedeutete "Erklären Sie es in Ihrer Antwort" ... unabhängig davon ... Brillante Lösung. Vielen Dank!
sfletche
12
Ich würde NICHT empfehlen, diesen Ansatz zu verwenden, da dies eine sehr irreführende Praxis ist. Es ist sehr verwirrend, wenn Sie Slice () verwenden und tatsächlich nichts in Scheiben schneiden. Wenn Sie eine unveränderliche Umkehrung benötigen, erstellen Sie einfach eine neue Kopie: const newArray = [... array] .reverse ()
Oleg Matei
103

In ES6:

const newArray = [...array].reverse()
Brian M. Hunt
quelle
2
Wie ist die Leistung dieser mit der der akzeptierten Antwort zu vergleichen? Sind sie gleich?
Katie
@Katie Sehr ähnlich, beide sehr schnell, wobei Chrome [...].reversein einem sehr einfachen Testfall einen Vorteil zu bieten scheint . jsperf.com/reverse-vs-slice-reverse/1
Brian M. Hunt
4
Ich werde immer .sliceschneller.
James Coyle
3
@JamesCoyle Es ist wahrscheinlich browser- und betriebssystemabhängig, aber slicewahrscheinlich schneller. B / C [...]ist ein generisches Iterable-to-Array und kann daher nicht so viele Annahmen treffen. Es ist auch wahrscheinlich, dass slicees besser optimiert ist, da es schon lange her ist.
Brian M. Hunt
Genau meine Gedanken.
James Coyle
11

Eine weitere ES6-Variante:

Wir können auch .reduceRight()ein umgekehrtes Array erstellen, ohne es tatsächlich umzukehren.

let A = ['a', 'b', 'c', 'd', 'e', 'f'];

let B = A.reduceRight((a, c) => (a.push(c), a), []);

console.log(B);

Nützliche Ressourcen:

Mohammad Usman
quelle
2
reduceRightist langsam af
Dragos Rizescu
@DragosRizescu Können Sie einige Beispieltestergebnisse teilen?
Mohammad Usman
1
Hier ist ein Repo, mit dem Sie spielen können: (nicht das beste Beispiel, aber ich habe dieses Argument vor einiger Zeit mit jemandem in einem React-Kontext gehabt, daher habe ich es zusammengestellt): github.com/rizedr/reduce-vs-reduceRight
Dragos Rizescu
4
(a, c) => a.concat([c])fühlt sich idiomatischer an als(a, c) => (a.push(c), a)
Kyle Lin
1
@DragosRizescu es sieht tatsächlich so aus, als wäre dies die schnellste der 3 Top-Antworten. jsperf.com/reverse-vs-slice-reverse/3
DBosley
7

Versuchen Sie diese rekursive Lösung:

const reverse = ([head, ...tail]) => 
    tail.length === 0
        ? [head]                       // Base case -- cannot reverse a single element.
        : [...reverse(tail), head]     // Recursive case

reverse([1]);               // [1]
reverse([1,2,3]);           // [3,2,1]
reverse('hello').join('');  // 'olleh' -- Strings too!                              
Austin Keeton
quelle
1
Dies scheint für leere Arrays zu brechen.
Matthias
6

Eine ES6-Alternative zur Verwendung .reduce()und Verbreitung.

const foo = [1, 2, 3, 4];
const bar = foo.reduce((acc, b) => ([b, ...acc]), []);

Grundsätzlich wird ein neues Array mit dem nächsten Element in foo erstellt und das akkumulierte Array für jede Iteration nach b verteilt.

[]
[1] => [1]
[2, ...[1]] => [2, 1]
[3, ...[2, 1]] => [3, 2, 1]
[4, ...[3, 2, 1]] => [4, 3, 2, 1]

Alternativ .reduceRight()wie hier oben erwähnt, jedoch ohne die .push()Mutation.

const baz = foo.reduceRight((acc, b) => ([...acc, b]), []);
hanswilw
quelle
4

Es gibt mehrere Möglichkeiten, ein Array umzukehren, ohne es zu ändern. Zwei von ihnen sind

var array = [1,2,3,4,5,6,7,8,9,10];

// Using Splice
var reverseArray1 = array.splice().reverse(); // Fastest

// Using spread operator
var reverseArray2 = [...array].reverse();

// Using for loop 
var reverseArray3 = []; 
for(var i = array.length-1; i>=0; i--) {
  reverseArray.push(array[i]);
}

Leistungstest http://jsben.ch/guftu

shekhardtu
quelle
0

IN einfaches Javascript:

function reverseArray(arr, num) {
  var newArray = [];
  for (let i = num; i <= arr.length - 1; i++) {
    newArray.push(arr[i]);
  }

  return newArray;
}
Amit Kumar
quelle
0

Umkehren mit variablem Tausch nur zu Demonstrationszwecken (Sie benötigen jedoch eine Kopie, wenn Sie nicht mutieren möchten).

const myArr = ["a", "b", "c", "d"];
const copy = [...myArr];
for (let i = 0; i < (copy.length - 1) / 2; i++) {  
    const lastIndex = copy.length - 1 - i; 
    [copy[i], copy[lastIndex]] = [copy[lastIndex], copy[i]] 
}
daino3
quelle
-4

es6:

const reverseArr = [1,2,3,4].sort(()=>1)
Radion Ponomarenko
quelle
4
Willkommen bei SO, Radion! Wenn Sie eine Antwort hinterlassen, ist es normalerweise eine gute Idee zu erklären, warum Ihre Antwort funktioniert und warum Sie zu diesem Schluss gekommen sind. Dies hilft neueren Benutzern, die von Ihnen angegebenen Interaktionen und Sprachen zu verstehen.
Ethan Field
In Radions Verteidigung: P, dass 1am Ende alles größer als Null gewesen sein könnte, denn so funktioniert Array.prototype.sortRückruf (oder so genannt compare function). Grundsätzlich vergleichen Sie immer 2 Zahlen und in diesem Fall wird der Vergleich immer positiv zurückgegeben, sodass immer die zweite Zahl vor der ersten angezeigt wird
iulial
8
sort()mutiert das Array (dh sortiert es an Ort und Stelle), was das OP vermeiden möchte.
Clint Harris
5
Diese Antwort ist in mehrfacher Hinsicht falsch. (1) es mutiert das Array, wie @ClintHarris hervorhebt, also ist es nicht besser als .reverse (). (2) Ihr Komparator ist illegal - wenn Sie 1 für a, b zurückgeben, müssen Sie eine negative Zahl für b, a zurückgeben. Wenn Ihre Antwort bei einigen Implementierungen das Array umkehrt, ist dies ein Glücksfall.
Don Hatch