Matriz inversa en Javascript sin mutar la matriz original


190

Array.prototype.reverse invierte el contenido de una matriz en su lugar (con mutación) ...

¿Existe una estrategia similarmente simple para revertir una matriz sin alterar el contenido de la matriz original (sin mutación)?



Aquí hay un punto de referencia que compara las diferentes opciones: jsben.ch/HZ7Zp
Solomon Ucko

Respuestas:


377

Puede utilizar slice () para hacer una copia a continuación inversa () se

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


¿Puedes por favor explicar slice () sin parámetros?
Alex

3
@Alex slice - If begin is omitted, slice begins from index 0.- entonces es lo mismo quearray.slice(0)
Arun P Johny

2
Creo que @Alex quería decir 'explícalo en tu respuesta' ... independientemente ... Solución brillante. ¡Gracias!
sfletche

14
NO recomendaría usar este enfoque, porque es una práctica muy engañosa. Es muy confuso cuando usas slice () y en realidad no estás cortando nada. Si necesita un reverso inmutable, simplemente cree una nueva copia nueva: const newArray = [... array] .reverse ()
Oleg Matei

105

En ES6:

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

2
¿Cómo se compara el rendimiento de esto con el de la respuesta aceptada? ¿Son lo mismo?
Katie

@Katie Muy similar, ambos muy rápidos, con Chrome pareciendo dar [...].reverseuna ventaja en un caso de prueba muy simple. jsperf.com/reverse-vs-slice-reverse/1
Brian M. Hunt

44
Constantemente me estoy volviendo .slicesignificativamente más rápido.
James Coyle el

3
@JamesCoyle Es probable que dependa del navegador y del sistema operativo, pero slicees probable que sea más rápido porque b / c [...]es un genérico iterable a matriz, por lo que no puede hacer tantas suposiciones. Además, es probable que sliceesté mejor optimizado b / c que haya existido durante mucho tiempo.
Brian M. Hunt el

Mis pensamientos exactamente.
James Coyle el

11

Otra variante ES6:

También podemos usar .reduceRight()para crear una matriz invertida sin realmente invertirla.

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

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

console.log(B);

Recursos utiles:


2
reduceRightes lento af
Dragos Rizescu

@DragosRizescu ¿Puedes compartir algunos resultados de prueba de muestra?
Mohammad Usman

1
Aquí hay un repositorio con el que puedes jugar: (no es el mejor ejemplo, pero tuve esta discusión con alguien hace un tiempo en un contexto de Reacción, por lo que lo he reunido): github.com/rizedr/reduce-vs-reduceRight
Dragos Rizescu

44
(a, c) => a.concat([c])se siente más idiomático que(a, c) => (a.push(c), a)
Kyle Lin

1
@DragosRizescu en realidad parece que esta es la más rápida de las 3 respuestas principales. jsperf.com/reverse-vs-slice-reverse/3
DBosley

7

Prueba esta solución recursiva:

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
Parece que se rompería para matrices vacías.
Matthias

6

Una alternativa ES6 usando .reduce()y difundiendo.

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

Básicamente, lo que hace es crear una nueva matriz con el siguiente elemento en foo y distribuir la matriz acumulada para cada iteración después de b.

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

Alternativamente, .reduceRight()como se mencionó anteriormente aquí, pero sin la .push()mutación.

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

4

Hay varias formas de invertir una matriz sin modificarla. Dos de ellos son

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

Prueba de rendimiento http://jsben.ch/guftu


0

EN Javascript simple:

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

  return newArray;
}

0

Invertir en su lugar con intercambio variable solo con fines demostrativos (pero necesita una copia si no desea mutar)

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)

44
Bienvenido a SO, Radion! Al dejar una respuesta, generalmente es una buena idea explicar por qué su respuesta funciona y por qué llegó a esta conclusión, esto ayuda a los usuarios más nuevos a comprender las interacciones y los idiomas que ha especificado.
Ethan Field

En defensa de Radion: P que 1al final podría haber sido algo mayor que cero, porque así es como funciona la Array.prototype.sortdevolución de llamada (o así llamada compare function). Básicamente, siempre se comparan 2 números y en este caso la comparación siempre es positiva, por lo que siempre se pasa al segundo número delante del primero :) esto es muy explicativo: stackoverflow.com/questions/6567941/…
iulial

8
sort()muta la matriz (es decir, la ordena en su lugar), que es lo que el OP quiere evitar.
Clint Harris

55
Esta respuesta es incorrecta de varias maneras. (1) muta la matriz, como señala @ClintHarris, por lo que no es mejor que .reverse (). (2) su comparador es ilegal: cuando devuelve 1 para a, b, debe devolver un número negativo para b, a. Si su respuesta invierte la matriz en algunas implementaciones, es completamente por suerte.
Don Hatch
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.