96 votes

Utiliser 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 peuvent ne pas être (et ne seront probablement pas) dans le même ordre dans chaque tableau. Chaque tableau ne devrait pas contenir plus de 10 objets. Je pensais que jQuery aurait une solution élégante à ce problème, mais je n'ai pas trouvé grand-chose en ligne.

Je sais qu'une brute imbriquée $.each(array, function(){}) La solution pourrait fonctionner, mais existe-t-il une fonction intégrée dont je n'ai pas connaissance ?

Merci.

281voto

Sudhakar R Points 3125

Il existe un moyen simple...

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

Si le résultat ci-dessus est vrai, les deux tableaux sont identiques, même si les éléments sont dans un ordre différent.

NOTE : Ceci ne fonctionne que pour les versions de jquery < 3.0.0 lors de l'utilisation d'objets JSON.

12 votes

+1, mais elle est vraie lorsque vous comparez un tableau avec un objet qui contient les mêmes propriétés, par ex. [0,1] == {0:0,1:1,length=2}

4 votes

Pourquoi $(arr1).not(arr2).length == 0 ne suffit pas ?

10 votes

@Alexxus, vous avez besoin des deux comparaisons car not est une fonction de filtrage et non une fonction d'égalité. Essayez-la avec [1,2] y [1] . En une seule commande, vous obtiendrez [] et dans un autre, vous obtiendrez [2] .

36voto

Anentropic Points 7751

Je l'ai également cherché aujourd'hui et je l'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 performance prises en compte.

J'aime l'idée d'une méthode d'aide jQuery. @David Je préférerais que votre méthode de comparaison fonctionne comme :

jQuery.compare(a, b)

Cela n'a pas de sens pour moi :

$(a).compare(b)

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

De même, en ce qui concerne le tri et la "mise en cache" des tableaux triés, il y a lieu de s'interroger sur l'efficacité de la mise en œuvre de ces mesures :

  • Je ne pense pas que le fait de trier une fois au début de la méthode au lieu de le faire à chaque fois dans la boucle constitue une "mise en cache". Le tri se fera toujours à chaque fois que vous appellerez compare(b). Ce n'est que de la sémantique, mais...
  • for (var i = 0 ; t[i] ; i++) { ...cette boucle se termine plus tôt si votre t contient une valeur fausse quelque part, donc $([1, 2, 3, 4]).compare([1, false, 2, 3]) retours vrai !
  • Plus important encore, la méthode array sort() trie le tableau en place Ainsi, l'action var b = t.sort() ...ne crée pas une copie triée du tableau original, elle trie le tableau original et attribue également un référence à elle en b . Je ne pense pas que la méthode de comparaison doive avoir des effets secondaires.

Il semble que nous devions copier les tableaux avant de travailler dessus. La meilleure réponse que j'ai pu trouver sur la façon de faire cela avec jQuery a été donnée par nul autre que John Resig ici sur SO ! Quelle est la manière la plus efficace de cloner un objet en JavaScript ? (voir les commentaires sur sa réponse pour la version array de la recette de clonage d'objets)

Dans ce cas, je pense que le code serait le suivant :

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]

2 votes

En fait, je nommerais probablement cette méthode "arrayCompare" plutôt que "compare" puisque c'est la seule chose sur laquelle elle est conçue pour fonctionner...

0 votes

C'est tout à fait exact. Merci beaucoup.

16voto

Kwex Points 859

Mon approche était tout à fait différente : j'ai aplati les deux collections à l'aide de JSON.stringify et j'ai utilisé une comparaison de chaînes normale pour vérifier l'égalité.

C'est-à-dire

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 : Veuillez noter que cette méthode suppose que les deux collections sont triées de la même manière, sinon elle donnerait un résultat erroné !

1 votes

J'avais besoin d'une méthode simple pour comparer des tableaux dans mes tests unitaires, en garantissant le même ordre pour les deux tableaux. C'est très bien, merci.

0 votes

Merci, vous m'avez sauvé la mise

14voto

Saiful Points 13

Convertir les deux tableaux en chaînes de caractères et les comparer

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

1 votes

Il semble bon de comparer des tableaux imbriqués et lorsque l'ordre est important.

3voto

Vinny Alves Points 31

J'ai trouvé cette discussion parce que j'avais besoin d'un moyen de comparer en profondeur des tableaux et des objets. En utilisant les exemples présentés ici, j'ai trouvé ce qui suit (divisé en 3 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;
    }
});

Essais

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X