Cómo clonar una matriz en JavaScript

JavaScript tiene muchas formas de hacer cualquier cosa. He escrito sobre 10 formas de escribir tubería / componer en JavaScript, y ahora estamos haciendo arreglos.

1. Operador de propagación (copia superficial)

Desde que cayó ES6, este ha sido el método más popular. Es una sintaxis breve y la encontrará increíblemente útil cuando use bibliotecas como React y Redux.

numbers = [1, 2, 3]; numbersCopy = [...numbers]; 

Nota: Esto no copia de forma segura matrices multidimensionales. Los valores de matriz / objeto se copian por referencia en lugar de por valor .

Esto esta bien

numbersCopy.push(4); console.log(numbers, numbersCopy); // [1, 2, 3] and [1, 2, 3, 4] // numbers is left alone 

Esto no esta bien

nestedNumbers = [[1], [2]]; numbersCopy = [...nestedNumbers]; numbersCopy[0].push(300); console.log(nestedNumbers, numbersCopy); // [[1, 300], [2]] // [[1, 300], [2]] // They've both been changed because they share references 

2. Buena antigua para bucle () (copia superficial)

Imagino que este enfoque es el menos popular, dado lo de moda que se ha vuelto la programación funcional en nuestros círculos.

Puro o impuro, declarativo o imperativo, ¡hace el trabajo!

numbers = [1, 2, 3]; numbersCopy = []; for (i = 0; i < numbers.length; i++) { numbersCopy[i] = numbers[i]; } 

Nota: Esto no copia de forma segura matrices multidimensionales. Como está utilizando el =operador, asignará objetos / matrices por referencia en lugar de por valor .

Esto esta bien

numbersCopy.push(4); console.log(numbers, numbersCopy); // [1, 2, 3] and [1, 2, 3, 4] // numbers is left alone 

Esto no esta bien

nestedNumbers = [[1], [2]]; numbersCopy = []; for (i = 0; i < nestedNumbers.length; i++) { numbersCopy[i] = nestedNumbers[i]; } numbersCopy[0].push(300); console.log(nestedNumbers, numbersCopy); // [[1, 300], [2]] // [[1, 300], [2]] // They've both been changed because they share references 

3. Good Old while () Loop (copia superficial)

Igual que for—impuro, imperativo, bla, bla, bla ... ¡funciona! ?

numbers = [1, 2, 3]; numbersCopy = []; i = -1; while (++i < numbers.length) { numbersCopy[i] = numbers[i]; } 

Nota: Esto también asigna objetos / matrices por referencia en lugar de por valor .

Esto esta bien

numbersCopy.push(4); console.log(numbers, numbersCopy); // [1, 2, 3] and [1, 2, 3, 4] // numbers is left alone 

Esto no esta bien

nestedNumbers = [[1], [2]]; numbersCopy = []; i = -1; while (++i < nestedNumbers.length) { numbersCopy[i] = nestedNumbers[i]; } numbersCopy[0].push(300); console.log(nestedNumbers, numbersCopy); // [[1, 300], [2]] // [[1, 300], [2]] // They've both been changed because they share references 

4. Array.map (copia superficial)

De vuelta en territorio moderno, encontraremos la mapfunción. Enraizado en las matemáticas, mapestá el concepto de transformar un conjunto en otro tipo de conjunto, conservando la estructura.

En inglés, eso significa que Array.mapdevuelve una matriz de la misma longitud cada vez.

Para duplicar una lista de números, use mapcon una doublefunción.

numbers = [1, 2, 3]; double = (x) => x * 2; numbers.map(double); 

¿Qué pasa con la clonación?

Es cierto que este artículo trata sobre la clonación de matrices. Para duplicar una matriz, simplemente devuelva el elemento en su mapllamada.

numbers = [1, 2, 3]; numbersCopy = numbers.map((x) => x); 

Si quieres ser un poco más matemático, (x) => xse llama identidad . Devuelve cualquier parámetro que se le haya dado.

map(identity) clona una lista.

identity = (x) => x; numbers.map(identity); // [1, 2, 3] 

Nota: Esto también asigna objetos / matrices por referencia en lugar de por valor .

5. Array.filter (copia superficial)

Esta función devuelve una matriz, como map, pero no se garantiza que tenga la misma longitud.

¿Qué pasa si estás filtrando por números pares?

[1, 2, 3].filter((x) => x % 2 === 0); // [2] 

La longitud de la matriz de entrada era 3, pero la longitud resultante es 1.

Sin embargo, si su filterpredicado siempre regresa true, obtendrá un duplicado.

numbers = [1, 2, 3]; numbersCopy = numbers.filter(() => true); 

Cada elemento pasa la prueba, por lo que se devuelve.

Nota: Esto también asigna objetos / matrices por referencia en lugar de por valor .

6. Array.reduce (copia superficial)

Casi me siento mal usando reducepara clonar una matriz, porque es mucho más poderoso que eso. Pero aquí vamos ...

numbers = [1, 2, 3]; numbersCopy = numbers.reduce((newArray, element) => { newArray.push(element); return newArray; }, []); 

reduce transforma un valor inicial mientras recorre una lista.

Aquí el valor inicial es una matriz vacía, y la vamos llenando con cada elemento a medida que avanzamos. Esa matriz debe devolverse de la función que se utilizará en la siguiente iteración.

Nota: Esto también asigna objetos / matrices por referencia en lugar de por valor .

7. Array.slice (copia superficial)

slicedevuelve una copia superficial de una matriz basada en el índice de inicio / finalización proporcionado.

Si queremos los primeros 3 elementos:

[1, 2, 3, 4, 5].slice(0, 3); // [1, 2, 3] // Starts at index 0, stops at index 3 

If we want all the elements, don’t give any parameters

numbers = [1, 2, 3, 4, 5]; numbersCopy = numbers.slice(); // [1, 2, 3, 4, 5] 

Note: This is a shallow copy, so it also assigns objects/arrays by reference instead of by value.

8. JSON.parse and JSON.stringify (Deep copy)

JSON.stringify turns an object into a string.

JSON.parse turns a string into an object.

Combining them can turn an object into a string, and then reverse the process to create a brand new data structure.

Note: This onesafely copies deeply nested objects/arrays!

nestedNumbers = [[1], [2]]; numbersCopy = JSON.parse(JSON.stringify(nestedNumbers)); numbersCopy[0].push(300); console.log(nestedNumbers, numbersCopy); // [[1], [2]] // [[1, 300], [2]] // These two arrays are completely separate! 

9. Array.concat (Shallow copy)

concat combines arrays with values or other arrays.

[1, 2, 3].concat(4); // [1, 2, 3, 4] [1, 2, 3].concat([4, 5]); // [1, 2, 3, 4, 5] 

If you give nothing or an empty array, a shallow copy’s returned.

[1, 2, 3].concat(); // [1, 2, 3] [1, 2, 3].concat([]); // [1, 2, 3] 

Note: This also assigns objects/arrays by reference instead of by value.

10. Array.from (Shallow copy)

This can turn any iterable object into an array. Giving an array returns a shallow copy.

numbers = [1, 2, 3]; numbersCopy = Array.from(numbers); // [1, 2, 3] 

Note: This also assigns objects/arrays by reference instead of by value.

Conclusion

Well, this was fun ?

I tried to clone using just 1 step. You’ll find many more ways if you employ multiple methods and techniques.