Odwróć tablicę w JavaScript bez mutowania oryginalnej tablicy


Odpowiedzi:


375

Można użyć slice () , aby wykonać kopię następnie reverse () go

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


Czy możesz wyjaśnić funkcję slice () bez parametrów?
Alex

3
@Alex slice - If begin is omitted, slice begins from index 0.- więc jest taki sam jakarray.slice(0)
Arun P. Johny

2
Myślę, że @Alex oznaczało „wyjaśnij to w swojej odpowiedzi” ... niezależnie od tego ... Świetne rozwiązanie. Dzięki!
sfletche

12
NIE zalecałbym stosowania tego podejścia, ponieważ jest to bardzo myląca praktyka. Jest to bardzo mylące, gdy używasz slice () i tak naprawdę niczego nie kroisz. Jeśli potrzebujesz niezmiennego odwrotu, po prostu utwórz świeżą nową kopię: const newArray = [... array] .reverse ()
Oleg Matei

104

W ES6:

const newArray = [...array].reverse()

2
Jak wypada to w porównaniu z przyjętą odpowiedzią? Czy oni są tacy sami?
Katie,

@Katie Bardzo podobne, oba bardzo szybkie, a Chrome wydaje się dawać [...].reverseprzewagę w bardzo prostym przypadku testowym. jsperf.com/reverse-vs-slice-reverse/1
Brian M. Hunt

4
Konsekwentnie robię się .sliceznacznie szybszy.
James Coyle

3
@JamesCoyle Prawdopodobnie zależy od przeglądarki i systemu operacyjnego, ale sliceprawdopodobnie będzie szybszy b / c [...]jest ogólną iterowalną tablicą, więc nie można przyjąć tylu założeń. Jest również prawdopodobne, że slicejest lepiej zoptymalizowany b / c, to już dawno temu.
Brian M. Hunt

Dokładnie moje myśli.
James Coyle

11

Kolejny wariant ES6:

Możemy również użyć .reduceRight()do utworzenia odwróconej tablicy bez jej odwracania.

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

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

console.log(B);

Przydatne zasoby:


2
reduceRightjest wolny af
Dragos Rizescu

@DragosRizescu Czy możesz podzielić się przykładowymi wynikami testów?
Mohammad Usman

1
Oto repozytorium, z którym możesz grać: (nie jest to najlepszy przykład, ale miałem ten argument z kimś jakiś czas temu w kontekście React, dlatego złożyłem
Dragos Rizescu

4
(a, c) => a.concat([c])czuje się bardziej idiomatyczny niż(a, c) => (a.push(c), a)
Kyle Lin,

1
@DragosRizescu faktycznie wygląda na to, że jest to najszybsza z 3 najlepszych odpowiedzi. jsperf.com/reverse-vs-slice-reverse/3
DBosley

7

Wypróbuj to rozwiązanie rekurencyjne:

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!                              

1
Wygląda na to, że zepsuje się dla pustych tablic.
Matthias,

6

Alternatywa ES6 przy użyciu .reduce()i rozprzestrzenianiu się.

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

Zasadniczo tworzy nową tablicę z następnym elementem w foo i rozkłada zgromadzoną tablicę dla każdej iteracji po b.

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

Alternatywnie, .reduceRight()jak wspomniano powyżej, ale bez .push()mutacji.

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

4

Istnieje wiele sposobów odwracania tablicy bez modyfikacji. Dwie z nich są

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]);
}

Test wydajności http://jsben.ch/guftu


0

INTO zwykły JavaScript:

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

  return newArray;
}

0

Cofanie w miejscu z zamianą zmiennych tylko w celach demonstracyjnych (ale potrzebujesz kopii, jeśli nie chcesz mutować)

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]] 
}

-4

es6:

const reverseArr = [1,2,3,4].sort(()=>1)

4
Witamy w SO, Radion! Przy pozostawianiu odpowiedzi zazwyczaj dobrze jest wyjaśnić, dlaczego odpowiedź działa i dlaczego doszedłeś do tego wniosku, pomaga to nowym użytkownikom w zrozumieniu określonych przez Ciebie interakcji i języków.
Ethan Field,

W obronie Radiona: P, że 1na końcu mogło być coś większego niż zero, ponieważ Array.prototype.sorttak compare functiondziała callback (lub tak zwany ). Zasadniczo zawsze porównujesz 2 liczby, w tym przypadku porównanie zawsze zwraca wartość dodatnią, więc zawsze mówi o przejściu do drugiej liczby przed pierwszą :) To bardzo objaśniające: stackoverflow.com/questions/6567941/…
iulial

8
sort()mutuje tablicę (tzn. sortuje ją na miejscu), czego OP chce uniknąć.
Clint Harris

5
Ta odpowiedź jest błędna na kilka sposobów. (1) mutuje tablicę, jak wskazuje @ClintHarris, więc nie jest lepsza niż .reverse (). (2) twój komparator jest nielegalny - gdy zwracasz 1 dla a, b, musisz zwrócić liczbę ujemną dla b, a. Jeśli twoja odpowiedź odwraca tablicę w niektórych implementacjach, dzieje się tak całkowicie przez szczęście.
Don Hatch
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.