使用jQuery比较两个Javascript对象数组


93

我想比较两个JavaScript对象数组,以查看它们是否相同。每个数组中的对象可能不会(并且很可能不会)以相同的顺序排列。每个数组不应有超过10个对象。我以为jQuery可以解决这个问题,但是我在网上找不到很多。

我知道可以使用简单的嵌套$.each(array, function(){})解决方案,但是有我不知道的内置函数吗?

谢谢。

Answers:


277

有一个简单的方法...

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

如果以上方法返回true,则即使元素的顺序不同,两个数组也相同。

注意:这仅适用于使用JSON对象时<3.0.0版的jquery版本


12
+1,但是当您将数组与包含相同属性的对象进行比较时,它等于true,例如f.ex[0,1] == {0:0,1:1,length=2}
David Hellsing

4
为什么$(arr1).not(arr2).length == 0还不够?
Alexxus 2014年

10
@Alexxus,您需要两个比较,因为它not是一个过滤器函数,而不是一个相等函数。尝试使用[1,2][1]。在一个顺序中,您将获得[],在另一个顺序中,您将获得[2]
2014年

3
请注意,如果数组中有重复项,则将返回true。所以类似:[[1,1,2,2,3,3] == [1,2,3]`是正确的。
Philll_t

3
not从3.0.0-rc1开始,jQuery 不再与通用对象一起使用。见github.com/jquery/jquery/issues/3147
马克-安德烈·Lafortune

35

我今天也在寻找这个东西,发现:http : //www.breakingpar.com/bkp/home.nsf/0/87256B280015193F87256BFB0077DFFD

尽管他们确实提到了一些性能考虑因素,但不知道这是否是一个好的解决方案。

我喜欢jQuery辅助方法的想法。@David我宁愿看到您的compare方法像这样工作:

jQuery.compare(a, b)

我对这样做没有任何意义:

$(a).compare(b)

其中a和b是数组。通常,当您使用$(something)时,您将传递选择器字符串以使用DOM元素。

同样关于排序和“缓存”已排序的数组:

  • 我不认为在方法开始时进行排序而不是每次通过循环进行排序都是“缓存”。每当您调用compare(b)时,排序仍然会发生。那只是语义,但是...
  • for(var i = 0; t [i]; i ++){ ...如果您的t数组在某处包含错误值,则此循环提前完成,因此$([1、2、3、4])。compare( [1,false,2,3])返回true
  • 更重要的是阵列sort()方法排序数组的地方,这样做VAR B = t.sort() ......不创建原始数组的排序副本,它的排序阵列,并分配一个参考,以在b中。我认为比较方法没有副作用。

看来我们需要做的是在处理数组之前先对其进行复制。对于以jQuery方式实现这一目标,我能找到的最佳答案就是John Resig。在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”,而不是“ compare”,因为这是它设计用于处理的唯一内容……
Anentropic 2011年

当场确实。非常感谢。
dimitarvp 2012年

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

注意:请注意,他的方法假设两个Collection都以相似的方式排序,否则,将给您错误的结果!


1
我需要一种简单的方法来比较单元测试中的数组,以确保两个数组的顺序相同。很好,谢谢。
aymericbeaumet 2014年

谢谢您救了我的一天
Sourabh Kumar Sharma 2015年

12

将两个数组都转换为字符串并进行比较

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

1
似乎比较嵌套数组和顺序很重要。
Pierre de LESPINAY 2014年

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中的每个对象进行比较。和| 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

如果(!equal)返回false,则可以移动;降低到$ .each的底部,以避免再次触发该函数。您可以返回平等;避免比较。
马特

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 2012年

1
@ScottJ Mr.AH问题是比较两个数组。排序后两个数组是否相等a [0] == b [0]。wtf你ba。
2012年

2
恐怕我不知道AH的含义,而Google毫无帮助。但是,如果我的评论太离谱了,为什么还要在2月21日完全重写此代码?
ScottJ 2012年

@ScottJ最有可能是AH === wtf
例外
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.