2017-09-19 123 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