HOWTO · JavaScript
Confronta due array in JavaScript
Questo tutorial introduce alcuni metodi per confrontare due array in JavaScript
In questa pagina
L’operatore === di JavaScript confronta gli array per identità: due array creati separatamente con gli stessi elementi non risultano uguali con questo controllo. Per confrontarne il contenuto, scegli una regola per l’ordine e per i valori degli elementi. Se i valori primitivi sono nello stesso ordine, confronta prima le lunghezze e poi ciascun elemento corrispondente. Usa JSON.stringify() solo se le sue regole di serializzazione sono adatte ai tuoi dati; se l’ordine non conta, confronta copie ordinate. Questi approcci di base confrontano gli array e gli oggetti annidati per riferimento, non per struttura.
Che cosa significa che due array sono uguali?
Per prima cosa, stabilisci che cosa significa «uguali» nel tuo caso. Un confronto ordinato richiede che gli array abbiano la stessa lunghezza e che ogni elemento corrisponda a quello nella stessa posizione. Un confronto indipendente dall’ordine considera gli array come collezioni, ma deve comunque tenere conto dei valori duplicati: [1, 1, 2] non equivale a [1, 2, 2], anche se entrambi contengono gli stessi valori distinti.
Stabilisci anche se il confronto degli elementi deve essere superficiale o strutturale. L’uguaglianza stretta è adatta a confrontare valori primitivi, come numeri e stringhe. Con oggetti e array annidati, invece, verifica se le due posizioni fanno riferimento allo stesso oggetto; non ne confronta le proprietà né il contenuto annidato.
Confrontare array in ordine con un ciclo o con Array.prototype.every()
Una funzione autonoma evita di modificare il prototipo incorporato Array.prototype. Questa versione controlla prima la lunghezza, poi confronta i valori corrispondenti con l’uguaglianza stretta. È un confronto ordinato e superficiale.
Esegui questo esempio:
Il codice e le etichette o gli output visibili in questa sezione restano in inglese.
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
La funzione rifiuta anche un valore modificato o array di lunghezza diversa. Queste chiamate aggiuntive sono esempi non eseguiti:
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"]));
La prima chiamata restituisce false perché il secondo elemento è diverso; la seconda restituisce false perché le lunghezze non coincidono.
Un ciclo for può applicare la stessa regola quando vuoi personalizzare il confronto per ogni posizione: rifiuta array di lunghezza diversa, restituisci false al primo elemento diverso e restituisci true quando tutte le posizioni corrispondono. Array.prototype.every() è più conciso e si interrompe non appena la funzione di callback restituisce false. Salta le posizioni non assegnate negli array sparsi, quindi con questi array il risultato può differire da quello di un ciclo che legge ogni indice. Se la distinzione è importante, usa array senza posizioni vuote oppure definisci come gestirle.
Confrontare array con JSON.stringify()
Se gli array contengono valori compatibili con JSON, confrontarne le rappresentazioni serializzate è conciso: JSON.stringify(left) === JSON.stringify(right). Il confronto tiene conto dell’ordine: [1, 2] e [2, 1] producono risultati diversi. La serializzazione segue inoltre regole specifiche: valori non supportati come undefined in un array vengono serializzati come null, mentre le proprietà degli oggetti il cui valore è undefined vengono omesse. Oggetti distinti con proprietà serializzabili equivalenti possono produrre la stessa rappresentazione, ma questo non definisce un’uguaglianza profonda generale. Anche l’ordine delle proprietà e il comportamento di serializzazione personalizzato possono influire sul risultato. Scegli questo metodo solo se le sue regole corrispondono al contratto dei dati; non usarlo come controllo universale di uguaglianza né presumere che sia più veloce con array grandi.
Confrontare array indipendentemente dall’ordine
Se l’ordine non conta e gli elementi sono valori primitivi, ordina copie superficiali e confronta gli elementi nelle posizioni risultanti. Chiamare sort() direttamente sugli array di input li modificherebbe: crea prima una copia con slice(). L’ordinamento predefinito confronta le rappresentazioni in stringa; se i valori richiedono un ordine diverso, per esempio quando sono numeri, fornisci una funzione di confronto. Ordinare richiede lavoro aggiuntivo e, con tipi diversi, serve una regola esplicita per stabilire l’ordine. Il controllo della lunghezza e degli elementi continua a preservare il numero di occorrenze dei valori.
Per le stringhe primitive, ordina le copie e confronta ogni valore risultante con l’uguaglianza stretta. Questo esempio completo non è stato eseguito; registra il risultato del confronto e i due array originali:
Il codice e le etichette o gli output visibili in questa sezione restano in inglese.
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);
Per questi array, la regola di confronto restituisce true e l’ordinamento delle copie lascia entrambi gli input nell’ordine originale. Ordinare entrambe le copie e confrontare ogni posizione preserva anche il numero di occorrenze: array con quantità diverse dello stesso valore non corrispondono. In questo esempio, l’ordinamento predefinito e l’uguaglianza stretta sono pensati per le stringhe; per tipi diversi servono una funzione di confronto e una regola di uguaglianza adatte. Per gli oggetti, definisci una chiave che rappresenti l’uguaglianza desiderata oppure usa una strategia di corrispondenza adatta a quei valori: l’ordinamento predefinito non stabilisce l’uguaglianza tra oggetti.
Gestire array e oggetti annidati
Gli esempi di confronto ordinato e di ordinamento usano l’uguaglianza stretta per ogni elemento. Di conseguenza, due valori creati separatamente, come [{ id: 1 }], risultano diversi in quella posizione anche se le loro proprietà visibili coincidono. Lo stesso vale per gli array annidati. Se serve un’uguaglianza strutturale, usa un confronto ricorsivo che definisca il comportamento per ogni tipo supportato oppure una libreria di confronto profondo progettata per l’applicazione. Prima di affidarti a questi strumenti, specifica come devono trattare date, mappe, insiemi, prototipi, riferimenti ciclici e valori numerici speciali: strumenti diversi possono implementare regole diverse.
Per dati sicuramente compatibili con JSON, la serializzazione può talvolta offrire un confronto strutturale conciso, tenendo presenti i limiti descritti sopra. Negli altri casi, definisci chiaramente il criterio di uguaglianza e verifica i casi rilevanti per l’applicazione. In pratica, scegli il metodo più semplice che rispetta i requisiti di ordine e semantica dei valori: every() o un ciclo per valori primitivi in ordine, la serializzazione per dati JSON soggetti a vincoli adeguati e una strategia esplicita di corrispondenza o uguaglianza profonda per gli altri requisiti.