Para duplicar una matriz en JavaScript: ¿cuál de los siguientes es más rápido de usar?
Método de corte
var dup_array = original_array.slice();
For
lazo
for(var i = 0, len = original_array.length; i < len; ++i)
dup_array[i] = original_array[i];
Sé que ambas formas solo hacen una copia superficial : si original_array contiene referencias a objetos, los objetos no se clonarán, pero solo se copiarán las referencias y, por lo tanto, ambas matrices tendrán referencias a los mismos objetos. Pero este no es el punto de esta pregunta.
Solo pregunto por la velocidad.
javascript
arrays
duplicates
copy
slice
Marco Demaio
fuente
fuente
Respuestas:
Hay al menos 5 (!) Formas de clonar una matriz:
Ha habido un hilo enorme de BENCHMARKS , que proporciona la siguiente información:
para los navegadores de parpadeo
slice()
es el método más rápido,concat()
es un poco más lento ywhile loop
es 2.4 veces más lento.para otros navegadores
while loop
es el método más rápido, ya que esos navegadores no tienen optimizaciones internas paraslice
yconcat
.Esto sigue siendo cierto en julio de 2016.
A continuación hay scripts simples que puede copiar y pegar en la consola de su navegador y ejecutar varias veces para ver la imagen. Producen milisegundos, menor es mejor.
mientras bucle
rebanada
Tenga en cuenta que estos métodos clonarán el objeto Array en sí, sin embargo, los contenidos de la matriz se copian por referencia y no se clonan en profundidad.
fuente
splice
y se sorprenderá (mientras ...)A.map(function(e){return e;});
Técnicamente
slice
es la forma más rápida. Sin embargo , es aún más rápido si agrega el0
índice de inicio.es más rápido que
http://jsperf.com/cloning-arrays/3
fuente
myArray.slice(0,myArray.length-1);
más rápido quemyArray.slice(0);
?¿qué pasa con es6 way?
fuente
[].concat(_slice.call(arguments))
arguments
viene ... Creo que su salida de babel está combinando algunas características diferentes. Es más probable que lo seaarr2 = [].concat(arr1)
.arr2 = [].conact(arr1)
es diferente dearr2 = [...arr1]
.[...arr1]
la sintaxis convertirá el agujero aundefined
. Por ejemplo,arr1 = Array(1); arr2 = [...arr1]; arr3 = [].concat(arr1); 0 in arr2 !== 0 in arr3
.n = 1000*1000; start = + new Date(); a = Array(n); b = [...a]; console.log(new Date() - start); // 168
[{a: 'a', b: {c: 'c'}}]
. Sic
se cambia el valor en la matriz "duplicada", cambiará en la matriz original, ya que es solo una copia referencial, no un clon.La forma más fácil de clonar profundamente una matriz u objeto:
fuente
undefined
ni ningúnfunction
s. Ambos serán convertidos anull
usted durante elJSON.stringify
proceso. Otras estrategias, como(['cool','array']).slice()
no las cambiarán, pero tampoco clonarán objetos en la matriz. Entonces hay una compensación.n = 1000*1000; start = + new Date(); a = Array(n); var b = JSON.parse(JSON.stringify(a)) console.log(new Date() - start); // 221
fuente
Puse una demostración rápida: http://jsbin.com/agugo3/edit
Mis resultados en Internet Explorer 8 son 156, 782 y 750, lo que indicaría que
slice
es mucho más rápido en este caso.fuente
a.map(e => e)
Es otra alternativa para este trabajo. A partir de hoy.map()
es muy rápido (casi tan rápido como.slice(0)
) en Firefox, pero no en Chrome.Por otro lado, si una matriz es multidimensional, ya que las matrices son objetos y los objetos son los tipos de referencia, ninguno de los métodos de división o de concat será una cura ... Así que una forma adecuada de la clonación de un array es una invención de
Array.prototype.clone()
lo sigue.fuente
🏁 La forma más rápida de clonar una matriz
Hice esta función de utilidad muy simple para probar el tiempo que lleva clonar una matriz. No es 100% confiable, sin embargo, puede darle una idea general de cuánto tiempo lleva clonar una matriz existente:
Y probado enfoque diferente:
ACTUALIZACIÓN :
Nota: de todos ellos, la única forma de clonar en profundidad una matriz es mediante el uso
JSON.parse(JSON.stringify(arr))
.Dicho esto, no use lo anterior si su matriz puede incluir funciones, ya que volverá
null
.Gracias @GilEpshtain por esta actualización .
fuente
arr => arr.slice()
es la más rápida.JSON.parse(JSON.stringify([function(){}]))
saldrá[null]
[...arr]
con4.653076171875ms
Chrome y8.565ms
Safari. El segundo rápido en Chrome es la función de divisiónarr.slice()
con6.162109375ms
y en Safari el segundo es[].concat(arr)
con13.018ms
.Echa un vistazo a: enlace . No se trata de velocidad, sino de comodidad. Además, como puede ver, solo puede usar el segmento (0) en tipos primitivos .
Para hacer una copia independiente de una matriz en lugar de una copia de la referencia, puede usar el método de división de matriz.
Ejemplo:
Fuente: enlace
fuente
for
bucle en la pregunta.Como @Dan dijo "Esta respuesta se vuelve obsoleta rápidamente. Use puntos de referencia para verificar la situación real", hay una respuesta específica de jsperf que no ha tenido una respuesta por sí misma: mientras que :
tuvo 960,589 operaciones / segundo con el segundo puesto
a.concat()
en 578,129 operaciones / segundo, que es 60%.Este es el último Firefox (40) de 64 bits.
@aleclarson creó un nuevo punto de referencia más confiable.
fuente
Forma ECMAScript 2015 con el
Spread
operador:Ejemplos básicos:
Prueba en la consola del navegador:
Referencias
fuente
Depende del navegador. Si mira en la publicación del blog Array.prototype.slice vs creación manual de matriz , hay una guía aproximada para el rendimiento de cada uno:
Resultados:
fuente
arguments
no es una matriz adecuada y está usandocall
para forzar laslice
ejecución de la colección Los resultados pueden ser engañosos.Hay una solución mucho más limpia:
Se requiere la verificación de longitud, porque el
Array
constructor se comporta de manera diferente cuando se llama con exactamente un argumento.fuente
splice()
, tal vez. Pero realmente, aplique y esto es todo menos intuitivo.Array.of
e ignorar la duración:Array.of.apply(Array, array)
Recuerde .slice () no funcionará para matrices bidimensionales. Necesitará una función como esta:
fuente
Depende de la longitud de la matriz. Si la longitud de la matriz es <= 1,000,000, los métodos
slice
yconcat
tardan aproximadamente el mismo tiempo. Pero cuando das un rango más amplio, elconcat
método gana.Por ejemplo, intente este código:
Si establece la longitud de original_array en 1,000,000, el
slice
método yconcat
método demoran aproximadamente el mismo tiempo (3-4 ms, dependiendo de los números aleatorios).Si establece la longitud de original_array en 10,000,000, entonces el
slice
método toma más de 60 ms y elconcat
método toma más de 20 ms.fuente
dup.push
está equivocadoa5
, en su lugar sedup[i] =
debe usarUna solución simple:
fuente
Entonces, para evitar que ocurran estos escenarios, use
fuente
cloneNums[0][0]
en su ejemplo propagó el cambionums[0][0]
, pero eso es porquenums[0][0]
efectivamente es un objeto cuya referencia es copiadacloneNums
por el operador de propagación. Todo lo que quiere decir, este comportamiento no afectará el código donde estamos copiando por valor (int, string, etc. literales).Tiempo de referencia!
Mis resultados:
Chrome (motor V8):
Firefox (motor SpiderMonkey):
fuente
Formas rápidas de duplicar una matriz en JavaScript en orden:
#1: array1copy = [...array1];
#2: array1copy = array1.slice(0);
#3: array1copy = array1.slice();
Si sus objetos de matriz contienen algún contenido no serializable JSON (funciones, Number.POSITIVE_INFINITY, etc.), mejor usar
array1copy = JSON.parse(JSON.stringify(array1))
fuente
Puedes seguir este código. Forma inmutable matriz clon. Esta es la manera perfecta de clonar en matriz
fuente
En ES6, simplemente puede utilizar la sintaxis Spread .
Ejemplo:
Tenga en cuenta que el operador de propagación genera una matriz completamente nueva, por lo que modificar una no afectará a la otra.
Ejemplo:
fuente