Sử dụng jQuery để so sánh hai mảng đối tượng Javascript


93

Tôi có hai mảng Đối tượng JavaScript mà tôi muốn so sánh để xem chúng có giống nhau không. Các đối tượng có thể không (và rất có thể sẽ không) theo cùng một thứ tự trong mỗi mảng. Mỗi mảng không được có nhiều hơn 10 đối tượng. Tôi nghĩ jQuery có thể có một giải pháp hữu ích cho vấn đề này, nhưng tôi không thể tìm thấy nhiều trên mạng.

Tôi biết rằng một $.each(array, function(){})giải pháp lồng nhau thô bạo có thể hoạt động, nhưng có bất kỳ chức năng tích hợp nào mà tôi không biết không?

Cảm ơn.

Câu trả lời:


277

Có một cách dễ dàng ...

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

Nếu ở trên trả về true, cả hai mảng đều giống nhau ngay cả khi các phần tử có thứ tự khác nhau.

LƯU Ý: Điều này chỉ hoạt động cho các phiên bản jquery <3.0.0 khi sử dụng các đối tượng JSON


12
+1, tuy nhiên nó bằng đúng khi bạn so sánh một Array với một đối tượng có chứa các tính chất tương tự, f.ex[0,1] == {0:0,1:1,length=2}
David Hellsing

4
tại sao $(arr1).not(arr2).length == 0là không đủ?
Alexxus

10
@Alexxus, bạn cần cả hai so sánh vì đây notlà một hàm lọc, không phải một hàm bình đẳng. Hãy thử nó với [1,2][1]. Theo một thứ tự, bạn sẽ nhận được [], và theo thứ tự khác, bạn sẽ nhận được [2].
Noyo

3
Lưu ý rằng nếu bạn có các bản sao trong một mảng, điều này sẽ trả về true. Vì vậy, một cái gì đó như: `[1,1,2,2,3,3] == [1,2,3]` là đúng.
Philll_t

3
jQuery notkhông còn hoạt động với các đối tượng chung kể từ 3.0.0-rc1. Xem github.com/jquery/jquery/issues/3147
Marc-André Lauckyne

35

Tôi cũng đang tìm kiếm điều này hôm nay và tìm thấy: http://www.breakpar.com/bkp/home.nsf/0/87256B280015193F87256BFB0077DFFD

Không biết đó có phải là một giải pháp tốt không mặc dù họ có đề cập đến một số cân nhắc về hiệu suất được tính đến.

Tôi thích ý tưởng về một phương thức trợ giúp jQuery. @David Tôi muốn xem phương pháp so sánh của bạn hoạt động như:

jQuery.compare(a, b)

Tôi không có ý nghĩa gì khi làm:

$(a).compare(b)

trong đó a và b là mảng. Thông thường, khi bạn $ (cái gì đó), bạn sẽ chuyển một chuỗi bộ chọn để làm việc với các phần tử DOM.

Cũng liên quan đến sắp xếp và 'bộ nhớ đệm' các mảng đã sắp xếp:

  • Tôi không nghĩ rằng sắp xếp một lần khi bắt đầu phương pháp thay vì mọi lần thông qua vòng lặp là 'bộ nhớ đệm'. Việc sắp xếp sẽ vẫn xảy ra mỗi khi bạn gọi so sánh (b). Đó chỉ là ngữ nghĩa, nhưng ...
  • for (var i = 0; t [i]; i ++) { ... vòng lặp này kết thúc sớm nếu mảng t của bạn chứa giá trị sai ở đâu đó, vì vậy $ ([1, 2, 3, 4]). so sánh ( [1, false, 2, 3]) trả về true !
  • Quan trọng hơn, phương thức array sort () sắp xếp mảng tại chỗ , do đó, thực hiện var b = t.sort () ... không tạo bản sao được sắp xếp của mảng ban đầu, nó sắp xếp mảng ban đầu và cũng chỉ định một tham chiếu tới nó trong b . Tôi không nghĩ rằng phương pháp so sánh sẽ có tác dụng phụ.

Có vẻ như những gì chúng ta cần làm là sao chép các mảng trước khi làm việc với chúng. Câu trả lời tốt nhất mà tôi có thể tìm thấy cho cách thực hiện điều đó theo cách jQuery không ai khác ngoài John Resig tại đây trên SO! Cách hiệu quả nhất để sao chép sâu một đối tượng trong JavaScript là gì? (xem nhận xét về câu trả lời của anh ấy cho phiên bản mảng của công thức nhân bản đối tượng)

Trong trường hợp đó, tôi nghĩ mã cho nó sẽ là:

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
thực sự tôi có lẽ muốn đặt tên cho phương pháp này 'arrayCompare' chứ không phải 'so sánh' vì đó là điều duy nhất nó được thiết kế để làm việc trên ...
Anentropic

Đúng vậy. Cảm ơn rất nhiều.
dimitarvp 13/10/12

14

Cách tiếp cận của tôi khá khác - tôi đã làm phẳng cả hai bộ sưu tập bằng cách sử dụng JSON.stringify và sử dụng so sánh chuỗi bình thường để kiểm tra sự bình đẳng.

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: Xin lưu ý rằng phương pháp của anh ấy giả định rằng cả hai Bộ sưu tập được sắp xếp theo kiểu giống nhau, nếu không, nó sẽ cho bạn một kết quả sai!


1
Tôi cần một phương pháp đơn giản để so sánh các mảng trong các bài kiểm tra đơn vị của mình, đảm bảo cùng một thứ tự cho hai mảng. Nó rất tốt, cảm ơn.
aymericbeaumet

Cảm ơn bạn đã cứu ngày của tôi
Sourabh Kumar Sharma

12

Chuyển đổi cả mảng thành chuỗi và so sánh

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

1
Có vẻ tốt để so sánh các mảng lồng nhau và khi thứ tự là quan trọng.
Pierre de LESPINAY

3

Tôi tìm thấy cuộc thảo luận này vì tôi cần một cách để so sánh sâu các mảng và đối tượng. Sử dụng các ví dụ ở đây, tôi đã nghĩ ra những điều sau (chia thành 3 phương pháp cho rõ ràng):

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

Thử nghiệm

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

Trong trường hợp của tôi, mảng được so sánh chỉ chứa sốchuỗi . Giải pháp này đã làm việc cho tôi:

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

Hãy thử nghiệm nó!

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

1

Tôi không nghĩ có cách "jQuery" tốt để làm điều này, nhưng nếu bạn cần hiệu quả, hãy ánh xạ một trong các mảng bằng một khóa nhất định (một trong các trường đối tượng duy nhất), sau đó so sánh bằng cách lặp qua mảng khác và so sánh với bản đồ hoặc mảng liên kết mà bạn vừa tạo.

Nếu hiệu quả không phải là một vấn đề, chỉ cần so sánh mọi đối tượng ở A với mọi đối tượng ở B. Miễn là | A | và | B | là nhỏ, bạn sẽ không sao.


@Stefan, cảm ơn vì phản hồi nhanh chóng. Bạn có thể đăng mã ví dụ cho ý tưởng lập bản đồ của mình không? Cảm ơn.
MegaMatt

1

Chà, nếu bạn chỉ muốn so sánh nội dung của các mảng, có một hàm jQuery hữu ích $ .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

Giải pháp tốt, nhưng tôi không chắc điều này có tính đến các mảng có các phần tử giống nhau, nhưng theo một thứ tự khác.
MegaMatt

Bạn có thể di chuyển nếu (! Bằng) trả về false; xuống dưới cùng của $ .each để tránh kích hoạt lại hàm. Và bạn có thể trả lại bằng nhau; để tránh bị so sánh.
Matt

1

Thay đổi mảng thành chuỗi và so sánh

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

1

Một lớp lót tuyệt vời từ Sudhakar R là phương thức toàn cầu 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;
  }
});

0

Tôi cũng tìm thấy điều này khi tìm cách thực hiện một số so sánh mảng với jQuery. Trong trường hợp của tôi, tôi có các chuỗi mà tôi biết là mảng:

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

Nhưng tôi quan tâm nếu đó là một trận đấu hoàn chỉnh hay chỉ một trận đấu một phần, vì vậy tôi đã sử dụng một cái gì đó như sau, dựa trên câu trả lời của 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

Nếu các bản sao có vấn đề [1, 1, 2]không nên bằng [2, 1]nhưng phải bằng nhau [1, 2, 1], đây là giải pháp đếm tham chiếu:

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

Đây là trò khó để chơi cùng .


0

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>


-3

Thử cái này

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

Điều đó sửa đổi cả a và b, và chỉ so sánh phần tử đầu tiên. wtf.
ScottJ

1
@ScottJ Mr.AH Câu hỏi là so sánh hai mảng .. Sau khi sắp xếp nếu cả hai mảng bằng nhau a [0] == b [0]. wtf bạn bah.
Ngoại lệ

2
Tôi e rằng tôi không biết AH nghĩa là gì, và google đã không giúp được gì. Nhưng nếu nhận xét của tôi không có cơ sở như vậy, tại sao mã này lại được viết lại hoàn toàn vào ngày 21 tháng 2?
ScottJ

@ScottJ Có lẽ nhất là AH === wtf
Ngoại lệ
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.