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 - for
impureza, 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 map
função. Enraizado na matemática, map
está o conceito de transformar um conjunto em outro tipo de conjunto, preservando a estrutura.
Em inglês, isso significa que Array.map
retorna uma matriz com o mesmo comprimento todas as vezes.
Para duplicar uma lista de números, use map
com uma double
funçã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 map
chamada.
numbers = [1, 2, 3]; numbersCopy = numbers.map((x) => x);
Se você gostaria de ser um pouco mais matemático, (x) => x
chama-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 filter
predicado 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 reduce
para 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)
slice
retorna 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.