功能检查"深度平等"嵌套对象

时间:2015-06-28 16:09:25

标签: javascript recursion javascript-objects deepequals

我正在尝试编写一个函数来检查两个对象是否具有相同的值。此函数要求我检查作为原始对象内的值存储的任何对象的相等性。我开发的方法(参见下面的代码)首先检查非对象值的相等性。然后,如果这些都匹配,我再次迭代对象并对原始函数进行递归调用,这允许我比较两个对象的每个嵌套级别。

但是,这种方法只能部分起作用。递归调用的本质意味着我只能检查对象中第一个键 - 值对的嵌套对象是否相等。一旦第一组嵌套对象被比较并且递归调用返回,我无法弄清楚如何检查包含嵌套对象的任何其他键值对。这是功能:

var deepEqual = function(val1, val2) {
  if (typeof val1 === 'object' && typeof val2 === 'object') {
      for (i in val1) {
        for (i in val2){
          if (typeof val1[i] !== 'object' && typeof val2[i] !== 'object') {
            if (val1[i] !== val2[i]) {
              return false
            }
          }
        }
      }
      for (i in val1) {
        for (i in val2){
          if (typeof val1[i] === 'object' && typeof val2[i] === 'object') {
            return deepEqual(val1[i], val2[i])
          }
        }
      }
    return true
  }
  else if (val1 === val2) {
    return true
  }
  else return false
}

我的基本问题是我相信我需要一个递归调用来检查嵌套对象的深度相等,但我只能成功检查一次。有人试图解决这样的问题吗?如果您需要更具体的内容,我会提供特定对象的结果示例。谢谢!

3 个答案:

答案 0 :(得分:1)

这是一种可能的解决方案,但我建议你找到属于自己的解决方案。

function isEqual(var1, var2) { // Break the comparison out into a neat little function
  if (typeof var1 !== "object") {
    return var1===var2;
  } else {
    return deepEqual(var1, var2);
  }
}

function deepEqual(var1, var2) {
   for (i in var1) { 
      if(typeof var2[i] === "undefined") { // Quick check, does the property even exist?
         return false;
      }
      if (!isEqual(var1[i], var2[i])) {
         return false;
      }
   }
   return true;
}

function areObjectsEqual(obj1, obj2) {
   return deepEqual(obj1, obj2) && deepEqual(obj2, obj1); // Two-way checking
}

您不仅需要检查obj1中是否存在obj2中的所有内容,还需要obj2obj1中的所有内容都存在。这个解决方案需要两种方式进行比较,但你可以大大优化它。

和一些测试用例

var v1 = { obj0:"jan", obj:{ name:"jan"}, obj2:"ben" }
var v2 = { obj:{ name:"jan"}, obj2:"ben" }

console.log(areObjectsEqual(v1, v2))

v1 = { obj:{ name:"jan"}, obj2:"ben" }
v2 = { obj:{ name:"jan"}, obj2:"ben" }

console.log(areObjectsEqual(v1, v2))

v1 = { obj:{ name:"jan2"}, obj2:"ben" }
v2 = { obj:{ name:"jan"}, obj2:"ben" }

console.log(areObjectsEqual(v1, v2))

v1 = { obj:{ name:"jan"}, obj2:"ben" }
v2 = { obj:{ name:"jan"}, obj2:"ben", obj3:"pig" }

console.log(areObjectsEqual(v1, v2))

答案 1 :(得分:1)

您可能想要的是_.isEquallodash库中的underscore

还有来自deepEqual断言库的Chai.js测试。

答案 2 :(得分:0)

一个简单的解决方案是JSON对对象进行字符串化并比较它们的字符串表示。正如@Jan提到的那样......

  

这仅在对象初始化完全相同时才有效   办法。如果属性相同但顺序不同,则会出现   失败

......这有点脆,但可能适合你的目的。