HOWTO · JavaScript
Comparar duas arrays em JavaScript
Este tutorial introduz alguns métodos para comparar duas arrays em JavaScript
Nesta página
O operador === do JavaScript compara arrays por identidade. Por isso, duas arrays criadas separadamente com o mesmo conteúdo não são iguais nessa comparação. Para comparar o conteúdo, defina uma regra para a ordem e para os valores dos elementos. Se os valores primitivos estiverem na mesma ordem, compare os comprimentos e, em seguida, cada elemento correspondente. Use JSON.stringify() somente quando as regras de serialização forem adequadas aos seus dados; se a ordem não importar, compare cópias ordenadas. Essas abordagens básicas comparam arrays e objetos aninhados por referência, não pela estrutura.
O que significa duas arrays serem iguais?
Primeiro, defina o que “igual” significa para o seu caso. Uma comparação ordenada exige que as arrays tenham o mesmo comprimento e que os elementos correspondentes em cada índice sejam iguais. Uma comparação independente da ordem trata as arrays como coleções, mas ainda precisa levar em conta os valores repetidos: [1, 1, 2] não equivale a [1, 2, 2] só porque ambas contêm os mesmos valores distintos.
Defina também se a igualdade dos elementos será rasa ou estrutural. A igualdade estrita funciona bem para comparar valores primitivos, como números e strings. Para objetos e arrays aninhados, ela verifica se as duas posições se referem ao mesmo objeto; não compara as propriedades nem o conteúdo interno.
Comparar arrays na ordem com um loop ou Array.prototype.every()
Uma função independente evita alterar o Array.prototype integrado ao JavaScript. Esta versão verifica primeiro os comprimentos e, em seguida, compara os valores correspondentes com igualdade estrita. É uma comparação ordenada e rasa.
Execute este exemplo:
O código e os rótulos ou saídas exibidos nesta seção permanecem em inglês.
function arraysEqual(left, right) {
if (left.length !== right.length) return false;
return left.every((value, index) => value === right[index]);
}
const first = ["red", "green", "blue"];
const second = ["red", "green", "blue"];
console.log(arraysEqual(first, second));
true
A função também rejeita um valor alterado e arrays de comprimentos diferentes. Estas chamadas adicionais são exemplos não executados:
function arraysEqual(left, right) {
if (left.length !== right.length) return false;
return left.every((value, index) => value === right[index]);
}
console.log(arraysEqual(["red", "green"], ["red", "blue"]));
console.log(arraysEqual(["red", "green"], ["red", "green", "blue"]));
A primeira chamada retorna false porque os segundos elementos são diferentes; a segunda retorna false porque os comprimentos diferem.
Um loop for expressa a mesma regra quando você quer personalizar a comparação em cada índice: rejeite comprimentos diferentes, retorne false na primeira divergência e retorne true depois que todas as posições corresponderem. Array.prototype.every() é mais conciso e para assim que a função de callback retorna false. Ele ignora posições não atribuídas em arrays esparsos, então o resultado pode ser diferente do de um loop que lê cada índice. Se essa diferença for relevante, use arrays densos ou defina como tratar as lacunas.
Comparar arrays com JSON.stringify()
Para arrays que contêm valores compatíveis com JSON, comparar as representações serializadas é conciso: JSON.stringify(left) === JSON.stringify(right). A comparação considera a ordem, então [1, 2] e [2, 1] produzem resultados diferentes. A serialização também tem regras próprias: valores não suportados, como undefined em um array, são serializados como null, enquanto propriedades de objetos cujo valor é undefined são omitidas. Objetos distintos com propriedades serializáveis equivalentes podem gerar a mesma representação, mas isso não define uma igualdade profunda geral. A ordem das propriedades e o comportamento de serialização personalizado também podem afetar o resultado. Use esse método somente quando essas regras corresponderem ao contrato dos seus dados; não o trate como uma verificação universal de igualdade nem presuma que seja mais rápido em arrays maiores.
Comparar arrays independentemente da ordem
Quando a ordem não importa e os elementos são primitivos, ordene cópias rasas e compare as posições resultantes. Chamar sort() diretamente nas entradas as modificaria; por isso, faça cópias primeiro com slice(). A ordenação padrão compara representações em string. Forneça uma função comparadora quando os valores precisarem de outra ordem, como no caso de números. Ordenar exige trabalho adicional, e tipos mistos requerem uma política de ordenação explícita. As verificações de comprimento e dos elementos continuam preservando a quantidade de valores repetidos.
Para strings primitivas, ordene cópias e compare cada valor resultante com igualdade estrita. Este exemplo completo, não executado, registra o resultado da comparação e as duas arrays originais:
O código e os rótulos ou saídas exibidos nesta seção permanecem em inglês.
function arraysHaveSameValues(left, right) {
if (left.length !== right.length) return false;
const sortedLeft = left.slice().sort();
const sortedRight = right.slice().sort();
return sortedLeft.every((value, index) => value === sortedRight[index]);
}
const left = ["pear", "apple", "pear"];
const right = ["pear", "pear", "apple"];
console.log(arraysHaveSameValues(left, right));
console.log(left);
console.log(right);
Para estas arrays, a regra de comparação retorna true, e ordenar as cópias mantém as duas entradas na ordem original. Ordenar ambas as cópias e comparar todas as posições também preserva a quantidade de valores repetidos: arrays com quantidades diferentes de um valor não correspondem. A ordenação padrão e a igualdade estrita deste exemplo são adequadas a strings; tipos mistos exigem uma função comparadora e uma regra de igualdade apropriadas. Para objetos, defina uma chave que represente a igualdade desejada ou use uma estratégia de correspondência adequada a esses valores; a ordenação padrão não estabelece igualdade entre objetos.
Lidar com arrays e objetos aninhados
Os exemplos de comparação ordenada e de ordenação usam igualdade estrita para cada elemento. Assim, dois valores criados separadamente, como [{ id: 1 }], são considerados diferentes nessa posição, mesmo que suas propriedades visíveis sejam iguais. O mesmo vale para arrays aninhados. Se você precisar de igualdade estrutural, use uma comparação recursiva que defina o comportamento para cada tipo aceito ou uma biblioteca de igualdade profunda apropriada à aplicação. Antes de confiar nela, especifique como deve tratar datas, mapas, conjuntos, protótipos, referências cíclicas e valores numéricos especiais; bibliotecas diferentes podem implementar contratos distintos.
Para dados sabidamente compatíveis com JSON, a serialização pode oferecer uma comparação estrutural concisa, respeitadas as limitações descritas acima. Caso contrário, explicite o contrato de igualdade e teste os casos relevantes para a aplicação. Na prática, escolha o método mais simples que corresponda aos requisitos de ordem e semântica dos valores: every() ou um loop para valores primitivos em ordem, serialização para dados JSON com restrições adequadas e uma estratégia deliberada de correspondência ou igualdade profunda para os demais casos.