Usando jQuery per confrontare due matrici di oggetti Javascript

Ho due array di oggetti JavaScript che vorrei confrontare per vedere se sono uguali. Gli oggetti potrebbero non (e molto probabilmente non lo saranno) nello stesso ordine in ogni array. Ogni array non deve avere più di 10 oggetti. Pensavo che jQuery potesse avere una soluzione elegante a questo problema, ma non ero in grado di trovare molto online.

So che una soluzione $.each(array, function(){}) annidata $.each(array, function(){}) potrebbe funzionare, ma c’è qualche funzione incorporata di cui non sono a conoscenza?

Grazie.

C’è un modo semplice …

 $(arr1).not(arr2).length === 0 && $(arr2).not(arr1).length === 0 

Se quanto sopra è vero, entrambi gli array sono uguali anche se gli elementi sono in ordine diverso.

NOTA: Funziona solo con le versioni jQuery <3.0.0 quando si usano oggetti JSON

Oggi stavo anche cercando questo e ho trovato: http://www.breakingpar.com/bkp/home.nsf/0/87256B280015193F87256BFB0077DFFD

Non so se questa è una buona soluzione anche se menzionano alcune considerazioni sulle prestazioni prese in considerazione.

Mi piace l’idea di un metodo helper jQuery. @ David mi piacerebbe vedere il tuo metodo di confronto per lavorare come:

 jQuery.compare(a, b) 

Non ho senso per me da fare:

 $(a).compare(b) 

dove a e b sono matrici. Normalmente quando $ (qualcosa) passeresti una stringa di selezione per lavorare con elementi DOM.

Anche per quanto riguarda l’ordinamento e il “caching” degli array ordinati:

  • Non penso che l’ordinamento una volta all’inizio del metodo invece che ogni volta che passi il ciclo sia ‘caching’. L’ordinamento si verificherà ancora ogni volta che si chiama compare (b). Questa è solo semantica, ma …
  • for (var i = 0; t [i]; i ++) { … questo ciclo termina presto se il tuo array t contiene un valore falso in esso da qualche parte, quindi $ ([1, 2, 3, 4]). [1, false, 2, 3]) restituisce true !
  • Ancora più importante il metodo array sort () ordina l’array in posizione , quindi var b = t.sort () … non crea una copia ordinata dell’array originale, ordina l’array originale e assegna anche un riferimento a in b . Non penso che il metodo di confronto debba avere effetti collaterali.

Sembra che quello che dobbiamo fare è copiare gli array prima di lavorarci. La migliore risposta che ho potuto trovare su come farlo in un modo jQuery è stata nientemeno che John Resig qui su SO! Qual è il modo più efficace per clonare in profondità un object in JavaScript? (vedi i commenti sulla sua risposta per la versione dell’array della ricetta di clonazione dell’object)

Nel qual caso penso che il codice per esso sarebbe:

 jQuery.extend({ compare: function (arrayA, arrayB) { if (arrayA.length != arrayB.length) { return false; } // sort modifies original array // (which are passed by reference to our method!) // so clone the arrays before sorting var a = jQuery.extend(true, [], arrayA); var b = jQuery.extend(true, [], arrayB); a.sort(); b.sort(); for (var i = 0, l = a.length; i < l; i++) { if (a[i] !== b[i]) { return false; } } return true; } }); var a = [1, 2, 3]; var b = [2, 3, 4]; var c = [3, 4, 2]; jQuery.compare(a, b); // false jQuery.compare(b, c); // true // c is still unsorted [3, 4, 2] 

Il mio approccio era abbastanza diverso: ho appiattito entrambe le raccolte usando JSON.stringify e ho usato un confronto di stringhe normali per verificare l’uguaglianza.

ie

 var arr1 = [ {Col: 'a', Val: 1}, {Col: 'b', Val: 2}, {Col: 'c', Val: 3} ]; var arr2 = [ {Col: 'x', Val: 24}, {Col: 'y', Val: 25}, {Col: 'z', Val: 26} ]; if(JSON.stringify(arr1) == JSON.stringify(arr2)){ alert('Collections are equal'); }else{ alert('Collections are not equal'); } 

NB: Si noti che il suo metodo presuppone che entrambe le collezioni siano ordinate in modo simile, in caso contrario, si otterrebbe un risultato falso!

Converti entrambi gli array in stringa e confronta

 if (JSON.stringify(array1) == JSON.stringify(array2)) { // your code here } 

Ho trovato questa discussione perché avevo bisogno di un modo per confrontare in profondità matrici e oggetti. Usando gli esempi qui, ho trovato il seguente (suddiviso in 3 metodi per maggiore chiarezza):

 jQuery.extend({ compare : function (a,b) { var obj_str = '[object Object]', arr_str = '[object Array]', a_type = Object.prototype.toString.apply(a), b_type = Object.prototype.toString.apply(b); if ( a_type !== b_type) { return false; } else if (a_type === obj_str) { return $.compareObject(a,b); } else if (a_type === arr_str) { return $.compareArray(a,b); } return (a === b); } }); jQuery.extend({ compareArray: function (arrayA, arrayB) { var a,b,i,a_type,b_type; // References to each other? if (arrayA === arrayB) { return true;} if (arrayA.length != arrayB.length) { return false; } // sort modifies original array // (which are passed by reference to our method!) // so clone the arrays before sorting a = jQuery.extend(true, [], arrayA); b = jQuery.extend(true, [], arrayB); a.sort(); b.sort(); for (i = 0, l = a.length; i < l; i+=1) { a_type = Object.prototype.toString.apply(a[i]); b_type = Object.prototype.toString.apply(b[i]); if (a_type !== b_type) { return false; } if ($.compare(a[i],b[i]) === false) { return false; } } return true; } }); jQuery.extend({ compareObject : function(objA,objB) { var i,a_type,b_type; // Compare if they are references to each other if (objA === objB) { return true;} if (Object.keys(objA).length !== Object.keys(objB).length) { return false;} for (i in objA) { if (objA.hasOwnProperty(i)) { if (typeof objB[i] === 'undefined') { return false; } else { a_type = Object.prototype.toString.apply(objA[i]); b_type = Object.prototype.toString.apply(objB[i]); if (a_type !== b_type) { return false; } } } if ($.compare(objA[i],objB[i]) === false){ return false; } } return true; } }); 

analisi

 var a={a : {a : 1, b: 2}}, b={a : {a : 1, b: 2}}, c={a : {a : 1, b: 3}}, d=[1,2,3], e=[2,1,3]; console.debug('a and b = ' + $.compare(a,b)); // a and b = true console.debug('b and b = ' + $.compare(b,b)); // b and b = true console.debug('b and c = ' + $.compare(b,c)); // b and c = false console.debug('c and d = ' + $.compare(c,d)); // c and d = false console.debug('d and e = ' + $.compare(d,e)); // d and e = true 

Nel mio caso gli array confrontati contengono solo numeri e stringhe . Questa soluzione ha funzionato per me:

 function are_arrs_equal(arr1, arr2){ return arr1.sort().toString() === arr2.sort().toString() } 

Proviamoci!

 arr1 = [1, 2, 3, 'nik'] arr2 = ['nik', 3, 1, 2] arr3 = [1, 2, 5] console.log (are_arrs_equal(arr1, arr2)) //true console.log (are_arrs_equal(arr1, arr3)) //false 

Non penso che ci sia un buon modo “jQuery” per farlo, ma se hai bisogno di efficienza, mappare uno degli array con una determinata chiave (uno dei campi object univoci), e poi fare il paragone eseguendo il looping attraverso l’altro array e confrontando la mappa o l’array associativo, che hai appena creato.

Se l’efficienza non è un problema, basta confrontare ogni object in A con ogni object in B. Finché | A | e | B | sono piccoli, dovresti stare bene.

Bene, se vuoi confrontare solo il contenuto degli array, c’è una utile funzione jQuery $ .inArray ()

 var arr = [11, "String #1", 14, "String #2"]; var arr_true = ["String #1", 14, "String #2", 11]; // contents are the same as arr var arr_false = ["String #1", 14, "String #2", 16]; // contents differ function test(arr_1, arr_2) { var equal = arr_1.length == arr_2.length; // if array sizes mismatches, then we assume, that they are not equal if (equal) { $.each(arr_1, function (foo, val) { if (!equal) return false; if ($.inArray(val, arr_2) == -1) { equal = false; } else { equal = true; } }); } return equal; } alert('Array contents are the same? ' + test(arr, arr_true)); //- returns true alert('Array contents are the same? ' + test(arr, arr_false)); //- returns false 

Cambia array in stringa e confronta

 var arr = [1,2,3], arr2 = [1,2,3]; console.log(arr.toString() === arr2.toString()); 

La bella fodera di Sudhakar R come metodo globale jQuery.

 /** * Compare two arrays if they are equal even if they have different order. * * @link https://stackoverflow.com/a/7726509 */ jQuery.extend({ /** * @param {array} a * First array to compare. * @param {array} b * Second array to compare. * @return {boolean} * True if both arrays are equal, otherwise false. */ arrayCompare: function (a, b) { return $(a).not(b).get().length === 0 && $(b).not(a).get().length === 0; } }); 

Ho anche trovato questo quando ho cercato di fare alcuni confronti con array con jQuery. Nel mio caso ho avuto archi che sapevo essere array:

 var needle = 'apple orange'; var haystack = 'kiwi orange banana apple plum'; 

Ma mi importava se si trattava di una partita completa o di una partita parziale, quindi ho usato qualcosa come il seguente, basato sulla risposta di Sudhakar R:

 function compareStrings( needle, haystack ){ var needleArr = needle.split(" "), haystackArr = haystack.split(" "), compare = $(haystackArr).not(needleArr).get().length; if( compare == 0 ){ return 'all'; } else if ( compare == haystackArr.length ) { return 'none'; } else { return 'partial'; } } 

Se i duplicati contano in modo tale che [1, 1, 2] non dovrebbe essere uguale a [2, 1] ma dovrebbe essere uguale a [1, 2, 1] , ecco una soluzione di conteggio dei riferimenti:

  const arrayContentsEqual = (arrayA, arrayB) => { if (arrayA.length !== arrayB.length) { return false} const refCount = (function() { const refCountMap = {}; const refCountFn = (elt, count) => { refCountMap[elt] = (refCountMap[elt] || 0) + count} refCountFn.isZero = () => { for (let elt in refCountMap) { if (refCountMap[elt] !== 0) { return false}} return true} return refCountFn})() arrayB.map(eltB => refCount(eltB, 1)); arrayA.map(eltA => refCount(eltA, -1)); return refCount.isZero()} 

Ecco il violino con cui giocare .

 var arr1 = [ {name: 'a', Val: 1}, {name: 'b', Val: 2}, {name: 'c', Val: 3} ]; var arr2 = [ {name: 'c', Val: 3}, {name: 'x', Val: 4}, {name: 'y', Val: 5}, {name: 'z', Val: 6} ]; var _isEqual = _.intersectionWith(arr1, arr2, _.isEqual);// common in both array var _difference1 = _.differenceWith(arr1, arr2, _.isEqual);//difference from array1 var _difference2 = _.differenceWith(arr2, arr1, _.isEqual);//difference from array2 console.log(_isEqual);// common in both array console.log(_difference1);//difference from array1 console.log(_difference2);//difference from array2 
  

Prova questo

 function check(c,d){ var a = c, b = d,flg = 0; if(a.length == b.length) { for(var i=0;i