2015-06-28 67 views
1

我想寫一個函數來檢查兩個對象是否有相同的值。該函數要求我檢查在原始對象內存儲爲值的任何對象的相等性。我開發的方法(見下面的代碼)首先檢查非對象值的相等性。然後,如果這些都匹配,我再次迭代對象並對原始函數進行遞歸調用,這允許我比較兩個對象的每個嵌套級別。函數檢查嵌套對象的「深度相等」

但是,這種方法只能部分起作用。遞歸調用的本質意味着我只能檢查對象中第一個鍵 - 值對的嵌套對象的相等性。一旦第一組嵌套對象被比較並且遞歸調用返回,我無法弄清楚如何檢查包含嵌套對象的任何附加鍵 - 值對。下面是函數:

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

你是說你不在乎物業名稱?順便說一句,'因爲(我在val1)(我在val2)'是災難性的。 – Bergi

+0

我正在檢查值。同意for循環不是最優 - 與我一起,我是一個沒有經驗的程序員,這是我第一次通過這個問題 – benpiggot

+0

所以你會期望'{a:1,b:2}'和'{a:2 ,b:1}'相等(因爲它們包含相同的值)? – Bergi

回答

0

一個簡單的解決方案是JSON將對象字符串化並比較它們的字符串表示形式。正如@Jan提到的...

這隻會在對象初始化方式完全相同的情況下才起作用 的方式。如果屬性相同,但順序不同,它將會 失敗

...這有點脆,但可能適合您的目的。

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 
} 

你不僅需要檢查,如果一切都在obj1obj2存在,而且在obj2,一切都在obj1存在。這種解決方案需要通過兩種方式進行比較,但您可以大大優化這一點。

而一些測試用例

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)) 
+0

感謝您這樣做 - 我對這個問題的指導是在一個函數中做到這一點 - 但這絕對有意義。感謝您在這方面的工作! – benpiggot

+0

多麼可怕的指令......這不是你想要編碼的方式,yuch。 – Jan

1

你可能想要的是從lodashunderscore_.isEqual

還有測試從Chai.js斷言庫。