Como clonar uma matriz em JavaScript

JavaScript tem muitas maneiras de fazer qualquer coisa. Eu escrevi sobre 10 maneiras de escrever pipe / compose em JavaScript e agora estamos fazendo matrizes.

1. Spread Operator (cópia rasa)

Desde que o ES6 caiu, este tem sido o método mais popular. É uma sintaxe breve e você a achará incrivelmente útil ao usar bibliotecas como React e Redux.

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

Observação: isso não copia matrizes multidimensionais com segurança. Os valores da matriz / objeto são copiados por referência em vez de por valor .

Isto é bom

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

Isso não está bem

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. Bom velho para () Loop (cópia rasa)

Imagino que essa abordagem seja a menos popular, dado o quão na moda a programação funcional se tornou em nossos círculos.

Puro ou impuro, declarativo ou imperativo, faz o trabalho!

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

Observação: isso não copia matrizes multidimensionais com segurança. Como você está usando o =operador, ele atribuirá objetos / matrizes por referência em vez de por valor .

Isto é bom

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

Isso não está bem

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. Bom e velho while () Loop (cópia superficial)

O mesmo que - forimpureza, imperativo, blá, blá, blá ... funciona! ?

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

Nota: Isso também atribui objetos / matrizes por referência em vez de por valor .

Isto é bom

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

Isso não está bem

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 (cópia superficial)

De volta ao território moderno, encontraremos a mapfunção. Enraizado na matemática, mapestá o conceito de transformar um conjunto em outro tipo de conjunto, preservando a estrutura.

Em inglês, isso significa que Array.mapretorna uma matriz com o mesmo comprimento todas as vezes.

Para duplicar uma lista de números, use mapcom uma doublefunção.

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

E a clonagem?

Verdade, este artigo é sobre clonagem de matrizes. Para duplicar um array, basta retornar o elemento em sua mapchamada.

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

Se você gostaria de ser um pouco mais matemático, (x) => xchama-se identidade . Ele retorna qualquer parâmetro fornecido.

map(identity) clona uma lista.

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

Nota: Isso também atribui objetos / matrizes por referência em vez de por valor .

5. Array.filter (cópia superficial)

Esta função retorna um array, assim como map, mas não é garantido que tenha o mesmo comprimento.

E se você estiver filtrando por números pares?

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

O comprimento da matriz de entrada era 3, mas o comprimento resultante é 1.

Se seu filterpredicado sempre retorna true, entretanto, você obtém uma duplicata!

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

Cada elemento passa no teste, então ele é retornado.

Nota: Isso também atribui objetos / matrizes por referência em vez de por valor .

6. Array.reduce (cópia superficial)

Quase me sinto mal usando reducepara clonar um array, porque é muito mais poderoso do que isso. Mas aqui vamos nós ...

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

reduce transforma um valor inicial ao percorrer uma lista.

Aqui, o valor inicial é um array vazio, e vamos preenchendo-o com cada elemento à medida que avançamos. Essa matriz deve ser retornada da função a ser usada na próxima iteração.

Nota: Isso também atribui objetos / matrizes por referência em vez de por valor .

7. Array.slice (cópia superficial)

sliceretorna uma cópia superficial de uma matriz com base no índice de início / fim fornecido que você fornece.

Se quisermos os 3 primeiros 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)

Isso pode transformar qualquer objeto iterável em uma matriz. Fornecer um array retorna uma cópia superficial.

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

Nota: Isso também atribui objetos / matrizes por referência em vez de por valor .

Conclusão

Bem, isso foi divertido?

Tentei clonar usando apenas 1 passo. Você encontrará muitas outras maneiras se utilizar vários métodos e técnicas.