ใช้ jQuery เพื่อเปรียบเทียบอาร์เรย์ของวัตถุ Javascript สองอาร์เรย์


93

ฉันมีอาร์เรย์ของ JavaScript Objects สองอาร์เรย์ที่ต้องการเปรียบเทียบเพื่อดูว่าเหมือนกันหรือไม่ วัตถุอาจไม่ (และส่วนใหญ่จะไม่) อยู่ในลำดับเดียวกันในแต่ละอาร์เรย์ แต่ละอาร์เรย์ไม่ควรมีมากกว่า 10 วัตถุ ฉันคิดว่า jQuery อาจมีทางออกที่ดีสำหรับปัญหานี้ แต่ฉันหาทางออนไลน์ไม่ได้มากนัก

ฉันรู้ว่า$.each(array, function(){})โซลูชันที่ซ้อนกันแบบเดรัจฉานสามารถทำงานได้ แต่มีฟังก์ชันในตัวที่ฉันไม่ทราบหรือไม่?

ขอบคุณ.

คำตอบ:


278

มีวิธีง่ายๆ ...

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

หากผลลัพธ์ข้างต้นเป็นจริงอาร์เรย์ทั้งสองจะเหมือนกันแม้ว่าองค์ประกอบจะอยู่ในลำดับที่ต่างกัน

หมายเหตุ: ใช้ได้เฉพาะกับ jquery เวอร์ชัน <3.0.0 เมื่อใช้ออบเจ็กต์ JSON


12
+1 อย่างไรก็ตามมันเท่ากับจริงเมื่อคุณเปรียบเทียบ Array กับ Object ที่มีคุณสมบัติเหมือนกัน f.ex[0,1] == {0:0,1:1,length=2}
David Hellsing

4
ทำไม$(arr1).not(arr2).length == 0ไม่พอ?
Alexxus

10
@Alexxus คุณต้องมีการเปรียบเทียบทั้งคู่เพราะnotเป็นฟังก์ชันตัวกรองไม่ใช่ฟังก์ชันความเท่าเทียมกัน ลองกับและ[1,2] [1]หนึ่งในการสั่งซื้อคุณจะได้รับและในอีกคุณจะได้รับ[] [2]
Noyo

3
โปรดทราบว่าหากคุณมีรายการที่ซ้ำกันในอาร์เรย์สิ่งนี้จะส่งกลับจริง สิ่งที่ชอบ: `[1,1,2,2,3,3] == [1,2,3]` เป็นจริง
Philll_t

3
jQuery notไม่ทำงานกับวัตถุทั่วไปที่ 3.0.0-rc1 อีกต่อไป ดูgithub.com/jquery/jquery/issues/3147
Marc-André Lafortune

35

ฉันกำลังมองหาสิ่งนี้ในวันนี้และพบ: http://www.breakingpar.com/bkp/home.nsf/0/87256B280015193F87256BFB0077DFFD

ไม่รู้ว่านั่นเป็นวิธีแก้ปัญหาที่ดีหรือไม่แม้ว่าพวกเขาจะกล่าวถึงการพิจารณาประสิทธิภาพบางอย่างที่นำมาพิจารณา

ฉันชอบแนวคิดของวิธีการช่วยเหลือ jQuery @ เดวิดฉันอยากจะเห็นวิธีเปรียบเทียบของคุณในการทำงานเช่น:

jQuery.compare(a, b)

ฉันไม่สมเหตุสมผลที่จะทำ:

$(a).compare(b)

โดยที่ a และ b เป็นอาร์เรย์ โดยปกติเมื่อคุณ$ (บางอย่าง)คุณจะส่งสตริงตัวเลือกเพื่อทำงานกับองค์ประกอบ DOM

นอกจากนี้เกี่ยวกับการเรียงลำดับและ 'แคช' อาร์เรย์ที่เรียงลำดับ:

  • ฉันไม่คิดว่าการเรียงลำดับครั้งเดียวในตอนเริ่มต้นของวิธีการแทนที่จะเป็นทุกครั้งในการวนซ้ำคือ 'แคช' การเรียงลำดับจะยังคงเกิดขึ้นทุกครั้งที่คุณเรียกเปรียบเทียบ (b) นั่นเป็นเพียงความหมาย แต่ ...
  • สำหรับ (var i = 0; t [i]; i ++) { ... ลูปนี้จะสิ้นสุดก่อนกำหนดหากอาร์เรย์tของคุณมีค่าเท็จอยู่ที่ไหนสักแห่งดังนั้น$ ([1, 2, 3, 4]) เปรียบเทียบ ( [1, false, 2, 3])คืนค่าจริง !
  • ที่สำคัญกว่านั้นคือวิธีการเรียงลำดับอาร์เรย์ () จะจัดเรียงอาร์เรย์ให้เข้าที่ดังนั้นการทำvar b = t.sort () ... จะไม่สร้างสำเนาที่เรียงลำดับของอาร์เรย์เดิม แต่จะเรียงลำดับอาร์เรย์เดิมและยังกำหนดการอ้างอิงให้ ในb . ฉันไม่คิดว่าวิธีการเปรียบเทียบควรมีผลข้างเคียง

ดูเหมือนว่าสิ่งที่เราต้องทำคือคัดลอกอาร์เรย์ก่อนที่จะทำงานกับพวกเขา คำตอบที่ดีที่สุดที่ฉันสามารถหาได้ในวิธีการทำ jQuery นั้นไม่ใช่ใครอื่นนอกจาก John Resig ที่นี่ใน SO! วิธีใดที่มีประสิทธิภาพที่สุดในการโคลนวัตถุใน JavaScript อย่างมีประสิทธิภาพที่สุด (ดูความคิดเห็นเกี่ยวกับคำตอบของเขาสำหรับสูตรการโคลนวัตถุรุ่นอาร์เรย์)

ในกรณีนี้ฉันคิดว่ารหัสของมันจะเป็น:

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
ที่จริงฉันอาจตั้งชื่อเมธอดนี้ว่า 'arrayCompare' มากกว่า 'เปรียบเทียบ' เพราะนั่นเป็นสิ่งเดียวที่ออกแบบมาเพื่อใช้งาน ...
Anentropic

จุดที่แน่นอน ขอบคุณมาก.
dimitarvp

14

แนวทางของฉันค่อนข้างแตกต่าง - ฉันแบนคอลเลกชันทั้งสองโดยใช้ JSON.stringify และใช้สตริงปกติเปรียบเทียบเพื่อตรวจสอบความเท่าเทียมกัน

ได้แก่

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

หมายเหตุ: โปรดทราบว่าวิธีการของเขาถือว่าทั้งสองคอลเลคชันถูกจัดเรียงในรูปแบบที่คล้ายคลึงกันหากไม่เป็นเช่นนั้นจะให้ผลลัพธ์ที่ผิดพลาด!


1
ฉันต้องการวิธีง่ายๆในการเปรียบเทียบอาร์เรย์ในการทดสอบหน่วยของฉันโดยให้แน่ใจว่าอาร์เรย์ทั้งสองมีลำดับเดียวกัน มันดีมากขอบคุณ
aymericbeaumet

ขอบคุณที่บันทึกวันของฉัน
Sourabh Kumar Sharma

12

แปลงอาร์เรย์ทั้งสองเป็นสตริงและเปรียบเทียบ

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

1
ดูเหมือนจะดีสำหรับการเปรียบเทียบอาร์เรย์ที่ซ้อนกันและเมื่อลำดับมีความสำคัญ
Pierre de LESPINAY

3

ฉันพบการสนทนานี้เพราะฉันต้องการวิธีเปรียบเทียบอาร์เรย์และวัตถุอย่างลึกซึ้ง จากตัวอย่างที่นี่ฉันได้สร้างสิ่งต่อไปนี้ (แบ่งออกเป็น 3 วิธีเพื่อความชัดเจน):

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

การทดสอบ

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

ในกรณีของฉันอาร์เรย์เทียบมีเพียงตัวเลขและสตริง วิธีนี้ใช้ได้ผลสำหรับฉัน:

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

มาทดสอบกัน!

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

ฉันไม่คิดว่าจะมีวิธี "jQuery" ที่ดีในการทำเช่นนี้ แต่ถ้าคุณต้องการประสิทธิภาพให้จับคู่อาร์เรย์หนึ่งในคีย์หนึ่ง (หนึ่งในช่องวัตถุที่ไม่ซ้ำกัน) จากนั้นทำการเปรียบเทียบโดยการวนลูปผ่านอาร์เรย์อื่น และเปรียบเทียบกับแผนที่หรืออาร์เรย์เชื่อมโยงที่คุณเพิ่งสร้างขึ้น

หากประสิทธิภาพไม่ใช่ปัญหาเพียงแค่เปรียบเทียบทุกออบเจ็กต์ใน A กับทุกออบเจ็กต์ใน B ตราบเท่าที่ | A | และ | B | ตัวเล็กคุณน่าจะโอเค


@ Stefan ขอบคุณสำหรับการตอบกลับอย่างรวดเร็ว คุณสามารถโพสต์โค้ดตัวอย่างสำหรับแนวคิดการทำแผนที่ของคุณได้หรือไม่ ขอบคุณ.
MegaMatt

1

ถ้าคุณต้องการเปรียบเทียบเฉพาะเนื้อหาของอาร์เรย์มีฟังก์ชัน 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

ทางออกที่ดี แต่ฉันไม่แน่ใจว่านี่เป็นการบัญชีสำหรับอาร์เรย์ที่มีองค์ประกอบเดียวกัน แต่เรียงลำดับต่างกัน
MegaMatt

คุณสามารถย้ายถ้า (! เท่ากับ) ส่งคืนเท็จ ลงไปที่ด้านล่างของ $ แต่ละเพื่อหลีกเลี่ยงการเริ่มทำงานของฟังก์ชันอีก และคุณสามารถคืนค่าเท่ากันได้ เพื่อหลีกเลี่ยงการเปรียบเทียบ
แมต

1

เปลี่ยนอาร์เรย์เป็นสตริงและเปรียบเทียบ

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

1

ซับที่ดีจากSudhakar Rเป็นวิธีการระดับโลกของ 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

ฉันยังพบสิ่งนี้เมื่อต้องการทำการเปรียบเทียบอาร์เรย์กับ jQuery ในกรณีของฉันฉันมีสตริงที่ฉันรู้ว่าเป็นอาร์เรย์:

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

แต่ฉันสนใจว่ามันเป็นการแข่งขันที่สมบูรณ์หรือเป็นการแข่งขันเพียงบางส่วนดังนั้นฉันจึงใช้สิ่งต่อไปนี้ตามคำตอบของ 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

หากรายการที่ซ้ำกันนั้น[1, 1, 2]ไม่ควรเท่ากับ[2, 1]แต่ควรจะเท่ากัน[1, 2, 1]นี่คือวิธีการนับอ้างอิง

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

นี่คือไวโอลินที่จะเล่นกับ


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

ลองทำตามนี้

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

ซึ่งปรับเปลี่ยนทั้ง a และ b และเปรียบเทียบเฉพาะองค์ประกอบแรก wtf.
ScottJ

1
@ScottJ Mr.AH คำถามคือการเปรียบเทียบอาร์เรย์สองอาร์เรย์ .. หลังจากเรียงลำดับแล้วว่าอาร์เรย์ทั้งสองมีค่าเท่ากันหรือไม่ a [0] == b [0] wtf คุณ bah.
ข้อยกเว้น

2
ฉันกลัวว่าฉันไม่รู้ว่า AH หมายถึงอะไรและ Google ก็ไม่ได้รับความช่วยเหลือ แต่ถ้าความคิดเห็นของฉันไม่ตรงประเด็นเหตุใดจึงเขียนโค้ดนี้ใหม่ทั้งหมดในวันที่ 21 ก.พ.
ScottJ

@ScottJ ส่วนใหญ่อาจเป็น AH === wtf
ข้อยกเว้น
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.