【问题标题】:Javascript Arrays - Checking two arrays of objects for same contents, ignoring orderJavascript Arrays - 检查两个对象数组的相同内容,忽略顺序
【发布时间】:2010-07-14 03:48:42
【问题描述】:

我有两个 JavaScript 数组(AB),其中包含我创建的对象。我想检查数组A中的所有对象是否都包含在数组B中,但不一定顺序相同。

最好的方法是什么?

编辑:

它们都是实际的对象,而不是原始对象,所以我还需要比较它们的内容和结构(可能使用类似 JSON.stringify 的东西)。

我想这样做是因为我正在学习测试驱动开发,并且我想测试返回对象列表的函数。我需要测试返回的列表中是否包含预期的对象(在这种情况下顺序无关紧要)。

【问题讨论】:

  • 它们是诸如truefalse23 之类的基元还是实际对象?你也能解释一下你为什么要这样做吗?可能有更好的方法。
  • 已编辑问题以供澄清。
  • 为什么不先排序再用JSON.stringify比较
  • 其实可以通过引用比较对象。
  • 您要比较的这些对象有多复杂?它们是否也具有您需要检查的特征(方法等)?

标签: javascript arrays comparison compare


【解决方案1】:

如果重复无关紧要,您可以使用lodash 制作单行。看看两个数组的差是否为空。

if (_(array).difference(otherArray).isEmpty()) {
    // is equal ignoring order and duplicates
}

console.log(_([1,2,3]).difference([2,3,1]).isEmpty()) // -> true
console.log(_([1,2,3,3]).difference([2,3,1,1]).isEmpty()) // -> also true

【讨论】:

    【解决方案2】:

    使用 ES6,您可以使用 every 和 some(以及 length)。

    let A = [1, 2, 3];
    let B = [2, 3, 1];
    
    // all objects in A are contained in B (A ⊆ B)
    // you can compare a <-> b however you'd like (here just `a === b`)
    let AsubB = A.every(a => B.some(b => a === b));
    
    // A and B are the same length
    let sameLength = A.length === B.length;
    
    // their contents are as equal as previously tested:
    let equal = AsubB && sameLength;
    

    【讨论】:

    • 检查是否包含,即使您使用两个方向,也不会考虑多个相等的元素;例如,考虑 [1,2,3,3] 和 [1,2,2,3]。
    • 检查两个对象属性很好;此外,在问题中不要求检查重复。我将它与一个包含从和到日期的对象一起使用,效果很好。
    【解决方案3】:

    用法: isEqArrays(arr1, arr2)

    //
    // Array comparsion
    //
    
    function inArray(array, el) {
      for ( var i = array.length; i--; ) {
        if ( array[i] === el ) return true;
      }
      return false;
    }
    
    function isEqArrays(arr1, arr2) {
      if ( arr1.length !== arr2.length ) {
        return false;
      }
      for ( var i = arr1.length; i--; ) {
        if ( !inArray( arr2, arr1[i] ) ) {
          return false;
        }
      }
      return true;
    }
    

    【讨论】:

    • 这比@ChaosPandion 的解决方案快吗?
    • 它是跨浏览器。混沌不是。他使用的语言功能还没有得到很好的支持。
    • 此代码不起作用:isEqArrays([0, 0, 1], [0, 1, 1]) 返回true
    【解决方案4】:

    这可能是最简单的方法,如果不是最慢的话。

    var o = { PropA: 1, PropB: 2 };
    var a = [1, 2, 3, 4, o];
    var b = [2, 3, 4, 1];
    
    var c = a.filter(function(value, index, obj) {
        return b.indexOf(value) > -1;
    });
    
    if (c.length !== a.length) {
        throw new Error("Array b is missing some elements!");
    }
    

    indexOf 只会检查它们是否引用了同一个对象。如果您想检查值等价性,则必须对属性进行深入比较或使用JSON.stringify,正如您在问题中提到的那样。

    【讨论】:

    • .indexOf 是否也检查对象等效性?例如,如果我创建一个o2 = { PropA: 2, PropB: 2} 并将其放入b,它会返回-1 以外的其他内容吗?
    • 与其他答案一样,这会返回 [0, 1, 1][0, 0, 1] 的误报。
    【解决方案5】:

    简约优雅

    function isEqual(arr1, arr2) {
        if (arr1.length !== arr2.length)
            return false;
        return arr1.every(x => arr2.includes(x));
    }
    

    如果重复很重要,请使用此

    function isEqual(arr1, arr2) {
        if (arr1.length !== arr2.length)
            return false;
        arr1.sort();
        arr2.sort();
        for (var i = 0; i < arr1.length; i++) {
            if (arr1[i] !== arr2[i])
                return false;
        }
        return true;
    }
    

    【讨论】:

    • isEqual([0, 1, 1], [0, 0, 1]) 返回真...
    猜你喜欢
    • 1970-01-01
    • 2012-06-10
    • 2021-11-06
    • 1970-01-01
    • 1970-01-01
    • 2013-03-21
    • 2014-02-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多