Używanie jQuery do porównywania dwóch tablic obiektów Javascript

Mam dwie tablice obiektów JavaScript, które chciałbym porównać, aby sprawdzić, czy są takie same. Obiekty nie mogą (i najprawdopodobniej nie będą) znajdować się w tej samej kolejności w każdej tablicy. Każda tablica nie powinna zawierać więcej niż 10 obiektów. Myślałem, że jQuery może mieć eleganckie rozwiązanie tego problemu, ale nie byłem w stanie znaleźć wiele w Internecie.

Wiem, że zagnieżdżone $.each(array, function(){}) rozwiązanie brute może działać, ale czy jest jakaś wbudowana funkcja, której nie jestem świadom?

Dzięki.
Author: MegaMatt, 2009-11-20

14 answers

Jest prosty sposób...

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

Jeśli powyższe zwraca true, obie tablice są takie same, nawet jeśli elementy są w innej kolejności.

Uwaga: to działa tylko dla wersji jquery

 269
Author: Sudhakar R,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-29 21:14:57

Ja też dziś tego szukałem i znalazłem: http://www.breakingpar.com/bkp/home.nsf/0/87256B280015193F87256BFB0077DFFD

Nie wiem, czy to dobre rozwiązanie, chociaż wspominają o pewnych aspektach wydajności wziętych pod uwagę.

Podoba mi się pomysł metody pomocniczej jQuery. @Dawid wolałbym zobaczyć Twoją metodę porównywania do pracy jak:

jQuery.compare(a, b)

Nie ma dla mnie sensu robić:

$(a).compare(b)

Gdzie a i b są tablicami. Zwykle, gdy $(something) przekazywałbyś łańcuch selektora do pracy z elementami DOM.

Również w odniesieniu do sortowania i "buforowania" posortowanych tablic:

  • Nie sądzę, aby sortowanie raz na początku metody zamiast za każdym razem przez pętlę było "buforowaniem". Sortowanie będzie miało miejsce za każdym razem, gdy wywołasz compare (b). To tylko semantyka, ale...
  • for (var i = 0; t [I]; i++) { ...pętla kończy się wcześnie, jeśli tablica T zawiera false wartość w niej gdzieś, więc $([1, 2, 3, 4]).compare([1, false, 2, 3]) zwraca true !
  • co ważniejsze metoda array sort () sortuje tablicę w miejsce, więc robi to var b = T.sort()...nie tworzy posortowanej kopii oryginalnej tablicy, sortuje tablicę oryginalną, a także przypisuje referencję do niej w b. Nie sądzę, żeby metoda porównywania miała skutki uboczne.

It seems what we need to do jest skopiowanie tablic przed rozpoczęciem pracy nad nimi. Najlepszą odpowiedzią, jaką mogłem znaleźć na to, jak to zrobić w jQuery, był nikt inny niż John Resig tutaj NA SO! jaki jest najbardziej efektywny sposób na głębokie sklonowanie obiektu w JavaScript? (Zobacz komentarze do jego odpowiedzi dla tablicy wersji receptury klonowania obiektów)

W takim przypadku myślę, że kod będzie:

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
Author: Anentropic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:19

Moje podejście było zupełnie inne - spłaszczyłem obie kolekcje używając JSON.stringify i użył zwykłego ciągu porównującego, aby sprawdzić równość.

Tzn.

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: proszę zauważyć, że jego metoda zakłada, że obie kolekcje są sortowane w podobny sposób, jeśli nie, to daje fałszywy wynik!

 12
Author: Kwex,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-30 14:27:48

Konwertuj obie tablice na ciąg znaków i porównaj

if (JSON.stringify(array1) == JSON.stringify(array2))
{
    // your code here
}
 11
Author: gmsi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-05 22:26:17

Znalazłem tę dyskusję, ponieważ potrzebowałem sposobu głębokiego porównywania tablic i obiektów. Korzystając z przykładów tutaj, wymyśliłem następujące (podzielone na 3 metody dla jasności):

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

Testowanie

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
Author: Vinny Alves,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-10 17:03:56

W moim przypadku porównywane tablice zawierają tylko liczby i ciągi . To rozwiązanie zadziałało dla mnie:

function are_arrs_equal(arr1, arr2){
    return arr1.sort().toString() === arr2.sort().toString()
}
Przetestujmy to!
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
Author: yesnik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-18 07:58:19

Myślę, że nie ma na to dobrego sposobu "jQuery" , ale jeśli potrzebujesz wydajności, odwzoruj jedną z tablic według określonego klucza (jedno z unikalnych pól obiektu), a następnie wykonaj porównanie przez zapętlenie drugiej tablicy i porównanie z mapą lub tablicą asocjacyjną, którą właśnie zbudowałeś.

Jeśli wydajność nie jest problemem, po prostu porównaj każdy obiekt w A Z Każdym obiektem w B. dopóki |A |i / B / są małe, powinno być dobrze.

 1
Author: Stefan Kendall,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-20 20:35:28

Cóż, jeśli chcesz porównać tylko zawartość tablic, jest przydatna funkcja 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
Author: Vilius Paulauskas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-20 21:06:16

Zmień tablicę na string i porównaj

var arr = [1,2,3], 
arr2 = [1,2,3]; 
console.log(arr.toString() === arr2.toString());
 1
Author: jay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-13 16:38:46

Nice one liner z Sudhakar R jako jQuery global method.

/**
 * 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
Author: Fleshgrinder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:15

Znalazłem to również, gdy szukałem porównania tablic z jQuery. W moim przypadku miałem ciągi, które wiedziałem, że są tablicami:

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

Ale zależało mi, czy to jest pełne dopasowanie, czy tylko częściowe, więc użyłem czegoś takiego, opartego na odpowiedzi Sudhakara 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
Author: Bung,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-08 00:47:12

Jeśli duplikaty mają znaczenie takie, że [1, 1, 2] nie powinny być równe [2, 1], ale powinny być równe [1, 2, 1], Oto rozwiązanie zliczające odniesienia:

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

Oto skrzypce do gry .

 0
Author: Paul Whipp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
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
Author: Parth Raval,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-10 10:52:10

Spróbuj tego

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
Author: Exception,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-21 05:08:03