Utilisation de jQuery pour comparer deux tableaux d'objets Javascript

j'ai deux tableaux D'objets JavaScript que j'aimerais comparer pour voir s'ils sont identiques. Les objets ne peuvent pas (et très probablement ne sera pas) être dans le même ordre dans chaque tableau. Chaque tableau ne devrait pas avoir plus de 10 objets. Je pensais que jQuery pourrait avoir une solution élégante à ce problème, mais je n'ai pas pu trouver beaucoup en ligne.

je sais qu'une solution brute emboîtée $.each(array, function(){}) pourrait fonctionner, mais y a-t-il une fonction intégrée dont je ne suis pas au courant?

Merci.

88
demandé sur MegaMatt 2009-11-20 23:31:27

14 réponses

Il y a un moyen facile...

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

si ce qui précède retourne true, les deux tableaux sont identiques même si les éléments sont dans un ordre différent.

NOTE: cela ne fonctionne que pour les versions jquery < 3.0.0 lors de l'utilisation des objets JSON

269
répondu Sudhakar R 2018-03-29 21:14:57

je cherchais aussi ceci aujourd'hui et j'ai trouvé: http://www.breakingpar.com/bkp/home.nsf/0/87256B280015193F87256BFB0077DFFD

Je ne sais pas si c'est une bonne solution, bien qu'ils mentionnent certaines considérations de rendement prises en compte.

j'aime l'idée d'une méthode jQuery helper. @David je préfère voir votre méthode de comparaison pour travailler comme:

jQuery.compare(a, b)

Je ne comprends pas faire:

$(a).compare(b)

où a et b sont des tableaux. Normalement, quand vous $(quelque chose) vous passez une chaîne de sélection pour travailler avec des éléments DOM.

également en ce qui concerne le tri et la mise en cache des tableaux triés:

  • Je ne pense pas que Trier une fois au début de la méthode au lieu de chaque fois à travers la boucle est 'caching'. Le sort se produira toujours chaque fois que vous appelez comparer(B). C'est juste de la sémantique, mais...
  • for (var i = 0; t[i]; i++) { ...cette boucle se termine tôt si votre tableau t contient une fausse valeur quelque part, donc $([1, 2, 3, 4]).comparer([1, false, 2, 3]) renvoie vrai !
  • plus important encore , la méthode array sort() trie le tableau en place , faisant ainsi var b = t. trier() ...ne crée pas une copie triée du tableau original, il trie le tableau original et lui assigne également un référence dans b . Je ne pense pas que la méthode de comparaison devrait avoir des effets secondaires.

Il semble que ce que nous devons faire est de copier les tableaux avant de travailler sur eux. La meilleure réponse que J'ai pu trouver pour savoir comment faire ça d'une manière jQuery était par nul autre que John Resig ici sur LE! Quel est le moyen le plus efficace de cloner profondément un objet en JavaScript? (voir les commentaires sur sa réponse pour la version Tableau de la recette de Clonage d'objet)

dans ce cas je pense que le code pour cela serait:

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]
34
répondu Anentropic 2017-05-23 11:47:19

mon approche était très différente - j'ai aplati les deux collections en utilisant JSON.stringify et utilisé une chaîne de caractères normale comparer pour vérifier l'égalité.

i. e.

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: s'il vous plaît noter que sa méthode suppose que les deux Collections sont triées de la même manière, sinon, il vous donnerait un résultat faux!

12
répondu Kwex 2012-08-30 14:27:48

Convertissez les deux tableaux en chaîne et comparez

if (JSON.stringify(array1) == JSON.stringify(array2))
{
    // your code here
}
11
répondu gmsi 2014-06-05 22:26:17

j'ai trouvé cette discussion parce que j'avais besoin d'un moyen de comparer profondément les tableaux et les objets. En utilisant les exemples ci-dessous, j'ai trouvé ce qui suit (divisé en trois méthodes pour plus de clarté):

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;
    }
});

test

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
3
répondu Vinny Alves 2011-09-10 17:03:56

dans mon cas, les tableaux comparatifs ne contiennent que des nombres et chaînes . Cette solution a fonctionné pour moi:

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

essayons!

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
2
répondu yesnik 2013-03-18 07:58:19

Je ne pense pas qu'il y ait une bonne façon "jQuery" de faire cela, mais si vous avez besoin d'efficacité, cartographiez un des tableaux par une certaine clé (un des champs d'objet uniques), puis faites la comparaison en faisant une boucle à travers l'autre tableau et en comparant avec la carte, ou tableau associatif, que vous venez de construire.

si l'efficacité n'est pas un problème, il suffit de comparer chaque objet de A à chaque objet de B. aussi longtemps que |A| et |B| sont petits, vous devriez être d'accord.

1
répondu Stefan Kendall 2009-11-20 20:35:28

bien, si vous voulez comparer seulement le contenu des tableaux, il y a une fonction utile 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
1
répondu Vilius Paulauskas 2009-11-20 21:06:16

Changement de tableau de string et de comparer les

var arr = [1,2,3], 
arr2 = [1,2,3]; 
console.log(arr.toString() === arr2.toString());
1
répondu jay 2013-08-13 16:38:46

La belle un paquebot de Sudhakar R comme jQuery méthode globale.

/**
 * 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;
  }
});
1
répondu Fleshgrinder 2017-05-23 12:18:15

j'ai aussi trouvé ceci en cherchant à faire des comparaisons avec jQuery. Dans mon cas, j'avais des cordes que je savais être des tableaux:

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

mais je me souciais si c'était une correspondance complète ou seulement une correspondance partielle, donc j'ai utilisé quelque chose comme ce qui suit, basé sur la réponse de 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';
  }
}
0
répondu Bung 2012-11-08 00:47:12

si les doublons sont tels que [1, 1, 2] ne doit pas être égal à [2, 1] mais doit être égal à [1, 2, 1] , voici une solution de comptage de référence:

  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()}

voici le violon pour jouer avec .

0
répondu Paul Whipp 2017-09-04 00:27:28

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 
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.js"></script>
0
répondu Parth Raval 2018-04-10 10:52:10

Essayez cette

function check(c,d){
  var a = c, b = d,flg = 0;
  if(a.length == b.length) 
  { 
     for(var i=0;i<a.length;i++) 
           a[i] != b[i] ? flg++ : 0; 
  } 
  else  
  { 
     flg = 1; 
  } 
  return flg = 0;
}
-3
répondu Exception 2012-02-21 05:08:03