2017-09-19 128 views
3

我有,我想比較像下面一個複雜的JSON對象:比較兩個對象與深度比較或與json.stringify?

$scope.new = [ 
    { 
    "name": "Node-1", 
    "isParent": true, 
    "text" : [ 
     { 
      "str" : "This is my first Node-1 string", 
      "parent":[] 
     }, 
     { 
      "str" : "This is my second Node-1 string", 
      "parent":[] 
     }], 
    "nodes": [ 
     { 
     "name": "Node-1-1", 
     "isParent": false, 
     "text" : [ 
      { 
      "str" : "This is my first Node-1-1 string", 
      "parent":[] 
      }, 
      { 
      "str" : "This is my second Node-1-1 string", 
      "parent":[] 
      }], 
      "nodes": [ 
      { 
      "name": "Node-1-1-1", 
      "isParent": false, 
      "text" : [ 
      { 
       "str" : "This is my first Node-1-1-1 string", 
       "parent":[] 
      }, 
      { 
       "str" : "This is my second Node-1-1-1 string", 
       "parent":[] 
      }], 
      "nodes": [] 
      } 
     ] 
     } 
    ] 
    } 
] 

但在比較我想也忽略1個屬性,但因爲我使用Angular.js我沒有看到任何選項angular.equal比較2個對象時將省略該屬性。

console.log(angular.equals($scope.new,$scope.copy)); 

所以,在做研究,我想出了下面的回答這是使用lodash已經發出的選擇,但問題是我想省略創建一個副本,我想我會在lodash的情況下性能下降。

Exclude some properties in comparison using isEqual() of lodash

所以,現在我想給對象轉換這樣的字符串,然後做對比,我想這將是快,但問題是,我怎麼會忽略這個屬性而字符串比較?

事情是這樣的:

var str1 = JSON.stringify(JSON.stringify($scope.new)); 

var str2 = JSON.stringify(JSON.stringify($scope.copy)); 

console.log(str1==str2); 

注:我想忽略isParent的特性,同時比較2對象。

什麼是比較2對象的最佳方法?

+1

您是否想要忽略'isParent'只頂部對象,還是所有嵌套對象以及比較? –

+0

@GuillermoMoratorio:在比較時,我想忽略所有嵌套對象中的isParent –

回答

1

如果使用_.isEqualWith您可以使用lodash並覆蓋用於深比較標準比較:

var objA = { 
 
    isParent: true, 
 
    foo: { 
 
    isParent: false, 
 
    bar: "foobar" 
 
    } 
 
}; 
 

 
var objB = { 
 
    isParent: false, 
 
    foo: { 
 
    isParent: true, 
 
    bar: "foobar" 
 
    } 
 
}; 
 

 
var comparator = function(left, right, key) { 
 
    if (key === 'isParent') return true; // if the key is 'isParent', mark the values equal 
 
    else return undefined;    // else fall back to the default behavior 
 
} 
 

 
var isEqual = _.isEqualWith(objA, objB, comparator); 
 

 
console.log(isEqual); // true
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>


排除多個屬性,因此延長了比較器功能:

var comparator = function(left, right, key) { 
    if (key === 'isParent' || key === 'anotherKey') return true; 
    else return undefined; 
} 

您還可以使用許多不同的方法語法,這取決於你喜歡什麼 - 一個switch語句,你遍歷數組...

+0

Upvoted表示您對我的幫助,但您認爲與lodash的比較會比字符串比較更快嗎? –

+0

性能取決於實施,將不得不進行測試。我很確定它不比比較字符串慢,因爲序列化本身並不是特別快。但是,除此之外,在字符串比較過程中,您將不得不處理忽略'isParent'屬性,因此實際上它不會節省任何東西。 – Timo

+0

好吧,但如果我想包括2至3個屬性,那我該如何包含它呢? –

2

轉換爲字符串是不是在這些情況下,最好的辦法。 保留它們作爲對象。

使用loadash:

const propertiesToExclude = ['isParent']; 
let result = _.isEqual(
    _.omit(obj1, propertiesToExclude), 
    _.omit(obj2, propertiesToExclude) 
); 

使用普通AngularJS,創建去掉不需要的屬性對象的副本,然後對它們進行比較:

let firstObj = angular.copy(obj1); 
let secondObj = angular.copy(obj2); 
const propertiesToExclude = ['isParent']; 
function removeNotComparatedProperties(obj) { 
    propertiesToExclude.forEach(prop => { 
    delete obj[prop]; 
    }); 
} 

removeNotComparatedProperties(firstObj); 
removeNotComparatedProperties(secondObj); 
angular.equals(firstObj, secondObj); 
+0

Upvoted爲你的善良努力去幫助我,但是你不認爲在角度的情況下,我們正在增加2個開銷,1是循環和刪除屬性,然後比較。 1解決方案會更快的東西:lodash或angukar方法? –

+0

讓我們開始說,對於你使用的物體,談論表演是非常沒用的。用於比較的排除屬性的數組長度相同。順便說一句,你認爲loadash在裏面做什麼?魔法?它們遍歷對象的屬性,並用你傳入的屬性檢查它們。 而'_.omit'創建對象的拷貝本身(比如'angular.copy')。 性能應該與我想的相差無幾,但如果您想要精確的答案,請使用jsperf,設置您的代碼並測試兩種情況下的性能:https://jsperf.com/ – quirimmo

+0

如果它是我的案件?這取決於。如果我已經在使用,或者我打算在其他地方使用loadash,我會使用loadash解決方案,因爲它更緊湊,更短。如果我只爲它包含loadash,我會通過第二個。 – quirimmo