Menggunakan jQuery untuk membandingkan dua array objek Javascript


93

Saya memiliki dua array Objek JavaScript yang ingin saya bandingkan untuk melihat apakah keduanya sama. Objek mungkin tidak (dan kemungkinan besar tidak akan) berada dalam urutan yang sama di setiap larik. Setiap larik tidak boleh memiliki lebih dari 10 objek. Saya pikir jQuery mungkin memiliki solusi elegan untuk masalah ini, tetapi saya tidak dapat menemukan banyak hal secara online.

Saya tahu bahwa $.each(array, function(){})solusi bersarang yang kasar dapat berfungsi, tetapi apakah ada fungsi bawaan yang tidak saya sadari?

Terima kasih.

Jawaban:


277

Ada cara mudah ...

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

Jika di atas mengembalikan nilai true, kedua lariknya sama meskipun elemennya dalam urutan yang berbeda.

CATATAN: Ini hanya berfungsi untuk jquery versi <3.0.0 saat menggunakan objek JSON


12
+1, namun itu sama benarnya jika Anda membandingkan Array dengan Objek yang berisi properti yang sama, f.ex[0,1] == {0:0,1:1,length=2}
David Hellsing

4
kenapa $(arr1).not(arr2).length == 0tidak cukup?
Alexxus

10
@Alexxus, Anda memerlukan kedua perbandingan karena notmerupakan fungsi filter, bukan fungsi kesetaraan. Cobalah dengan [1,2]dan [1]. Dalam satu urutan, Anda akan mendapatkan [], dan di tempat lain, Anda akan mendapatkan [2].
Noyo

3
Perhatikan bahwa jika Anda memiliki duplikat dalam larik, ini akan mengembalikan nilai true. Jadi sesuatu seperti: `[1,1,2,2,3,3] == [1,2,3]` benar.
Philll_t

3
jQuery nottidak lagi berfungsi dengan objek umum mulai 3.0.0-rc1. Lihat github.com/jquery/jquery/issues/3147
Marc-André Lafortune

35

Saya juga mencari ini hari ini dan menemukan: http://www.breakingpar.com/bkp/home.nsf/0/87256B280015193F87256BFB0077DFFD

Tidak tahu apakah itu solusi yang baik meskipun mereka menyebutkan beberapa pertimbangan kinerja yang diperhitungkan.

Saya suka ide metode pembantu jQuery. @David Saya lebih suka melihat metode perbandingan Anda berfungsi seperti:

jQuery.compare(a, b)

Saya tidak masuk akal bagi saya untuk melakukan:

$(a).compare(b)

dimana a dan b adalah array. Biasanya ketika Anda $ (sesuatu) Anda akan melewati string pemilih untuk bekerja dengan elemen DOM.

Juga tentang pengurutan dan 'caching' array yang diurutkan:

  • Saya tidak berpikir mengurutkan sekali pada awal metode alih-alih setiap kali melalui loop adalah 'caching'. Pengurutan akan tetap terjadi setiap kali Anda memanggil bandingkan (b). Itu hanya semantik, tapi ...
  • for (var i = 0; t [i]; i ++) { ... loop ini selesai lebih awal jika array t Anda berisi nilai yang salah di dalamnya, jadi $ ([1, 2, 3, 4]). bandingkan ( [1, false, 2, 3]) mengembalikan nilai true !
  • Lebih penting lagi metode array sort () mengurutkan array di tempat , jadi melakukan var b = t.sort () ... tidak membuat salinan yang diurutkan dari array asli, itu mengurutkan array asli dan juga memberikan referensi ke itu di b . Saya tidak berpikir metode perbandingan harus memiliki efek samping.

Sepertinya yang perlu kita lakukan adalah menyalin array sebelum mengerjakannya. Jawaban terbaik yang dapat saya temukan untuk bagaimana melakukan itu dengan cara jQuery tidak lain adalah oleh John Resig di SO! Apa cara paling efisien untuk mengkloning objek dalam JavaScript? (lihat komentar pada jawabannya untuk versi array dari resep kloning objek)

Dalam hal ini saya pikir kode untuk itu adalah:

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
sebenarnya saya mungkin akan menamai metode ini 'arrayCompare' daripada 'bandingkan' karena hanya itu yang dirancang untuk bekerja ...
Anentropic

Tepat sekali. Terima kasih banyak.
dimitarvp

14

Pendekatan saya sangat berbeda - saya meratakan kedua koleksi menggunakan JSON.stringify dan menggunakan perbandingan string normal untuk memeriksa kesetaraan.

Yaitu

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: Harap dicatat bahwa metodenya mengasumsikan bahwa kedua Koleksi diurutkan dengan cara yang sama, jika tidak, itu akan memberi Anda hasil yang salah!


1
Saya membutuhkan metode sederhana untuk membandingkan array dalam pengujian unit saya, memastikan urutan yang sama untuk dua array. Sangat bagus, terima kasih.
aymericbeaumet

Terima kasih Anda menyelamatkan hari saya
Sourabh Kumar Sharma

12

Ubah kedua larik menjadi string dan bandingkan

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

1
Tampaknya bagus untuk membandingkan larik bersarang dan saat urutan itu penting.
Pierre de LESPINAY

3

Saya menemukan diskusi ini karena saya membutuhkan cara untuk membandingkan array dan objek secara mendalam. Menggunakan contoh di sini, saya menemukan yang berikut (dipecah menjadi 3 metode untuk kejelasan):

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

Menguji

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

Dalam kasus saya, array yang dibandingkan hanya berisi angka dan string . Solusi ini berhasil untuk saya:

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

Mari kita uji!

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

Menurut saya tidak ada cara "jQuery" yang baik untuk melakukan ini, tetapi jika Anda memerlukan efisiensi, petakan salah satu array dengan kunci tertentu (salah satu bidang objek unik), lalu lakukan perbandingan dengan mengulang melalui array lainnya dan membandingkannya dengan peta, atau larik asosiatif, yang baru saja Anda buat.

Jika efisiensi tidak menjadi masalah, bandingkan saja setiap objek di A dengan setiap objek di B. Selama | A | dan | B | kecil, kamu harus baik-baik saja.


@ Stefan, terima kasih atas tanggapan yang cepat. Dapatkah Anda memposting kode contoh untuk ide pemetaan Anda? Terima kasih.
MegaMatt

1

Nah, jika Anda hanya ingin membandingkan konten array, ada fungsi jQuery $ .inArray () yang berguna

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

Solusi bagus, tetapi saya tidak yakin ini memperhitungkan array yang memiliki elemen yang sama, tetapi dalam urutan yang berbeda.
MegaMatt

Anda dapat memindahkan if (! Equal) return false; turun ke bagian bawah $ .each untuk menghindari pengaktifan fungsi lagi. Dan Anda bisa kembali sama; untuk menghindari perbandingan.
Matt

1

Ubah array menjadi string dan bandingkan

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

1

Satu liner bagus dari Sudhakar R sebagai metode global 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

Saya juga menemukan ini ketika ingin melakukan beberapa perbandingan array dengan jQuery. Dalam kasus saya, saya memiliki string yang saya tahu sebagai array:

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

Tapi saya peduli apakah itu pertandingan lengkap atau hanya pertandingan parsial, jadi saya menggunakan sesuatu seperti berikut ini, berdasarkan jawaban 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

Jika duplikat penting sehingga [1, 1, 2]tidak boleh sama [2, 1]tetapi harus sama [1, 2, 1], berikut adalah solusi penghitungan referensi:

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

Ini biola untuk dimainkan .


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

Coba ini

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

Itu mengubah a dan b, dan hanya membandingkan elemen pertama. wtf.
ScottJ

1
@ScottJ Mr.AH Pertanyaannya adalah membandingkan dua larik .. Setelah menyortir apakah kedua larik sama dengan a [0] == b [0]. wtf kamu bah.
Pengecualian

2
Saya khawatir saya tidak tahu apa artinya AH, dan google tidak membantu. Tetapi jika komentar saya sangat tidak berdasar, mengapa kode ini sepenuhnya ditulis ulang pada 21 Februari?
ScottJ

@ScottJ Kemungkinan besar AH === wtf
Pengecualian
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.