2012-03-06 14 views
87

Supongamos que quería una función de clasificación que devuelve una copia ordenada de la matriz ingresada. I ingenuamente intentado esto¿Cómo se puede ordenar una matriz sin mutar la matriz original?

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

y lo probé con esto, lo que demuestra que mi método sort está mutando la matriz.

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" 

También probé este enfoque

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

pero no funciona en absoluto.

¿Hay una manera directa de evitar esto, preferiblemente de una manera que no requiera laminar manualmente mi propio algoritmo de clasificación o copiar cada elemento de la matriz en uno nuevo?

+0

crear una copia profunda de la matriz y ordenarla en su lugar. – evanmcdonnal

+0

@evanmcdonnal Una copia superficial podría ser lo suficientemente buena si se quiere todo es un reordenamiento y no un duplicado de cada elemento en el conjunto. – Kekoa

+0

'.sort' requiere que el valor' this' sea la matriz, por lo que para que el último fragmento funcione, '.sort.call (arr)' (aunque no resuelve el problema). – pimvdb

Respuesta

101

Copie la matriz. Hay muchas maneras de hacerlo:

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

// Or: 
return Array.prototype.slice.call(arr).sort(); // For array-like objects 
+0

¿Hará esto una copia profunda, es decir, los objetos anidados y las matrices también se copiarán? –

+0

¿Hay alguna ventaja al usar 'concat' sobre say' slice (0) 'o son casi iguales? – JaredPar

+0

@JaredPar El resultado es igual. Si realmente desea un micro rendimiento, puede configurar (o buscar) un control de rendimiento en http://jsperf.com/ –

32

intente lo siguiente

function sortCopy(arr) { 
    return arr.slice(0).sort(); 
} 

La expresión slice(0) crea una copia de la matriz empezando por el elemento 0.

+18

+1, '.slice()' también funciona. – pimvdb

16

Puede utilizar rebanada sin argumentos para copiar una matriz:

var foo, 
    bar; 
foo = [3,1,2]; 
bar = foo.slice().sort(); 
+0

no copia para mí – Rbjz

+2

@ RobertCutajar-Robajz, copie ese fragmento como está en su consola de desarrollo y funcionará perfectamente. Si tiene problemas, no está con el código en esta respuesta. – zzzzBov

+0

cierto, tenía un script en caché. Funciona. – Rbjz

-1

utilizo Object.assign() para la mayoría de mis copias:

var copyArray = Object.assign([], originalArray).sort(); 

Sin embargo, después de mirar a través de los comentarios OP, he investigado un poco de copia profunda y resulta que Object.assign no sólo realiza una copia superficial, sino sólo selecciona propiedades enumerables y propias (como se responde en this post). solución

0

Usted también puede hacer esto

d = [20, 30, 10] 
e = Array.from(d) 
e.sort() 

Esta forma d no se mutará.

function sorted(arr) { 
    temp = Array.from(arr) 
    return temp.sort() 
} 

//Use it like this 
x = [20, 10, 100] 
console.log(sorted(x))