How can I get a list of the differences between two JavaScript object graphs?

前端 未结 10 472
终归单人心
终归单人心 2020-11-29 01:02

I want to be able to get a list of all differences between two JavaScript object graphs, with the property names and values where the deltas occur.

For what it is w

相关标签:
10条回答
  • 2020-11-29 01:14

    var d = { 
       FirstName : "John", 
       LastName : "Doh", 
       Age : 30, 
       EMailAddresses : [
          "john.doe@gmail.com", 
          "jd@initials.com"
       ], 
       Children : [ 
          { 
             FirstName : "Sara", 
             LastName : "Doe", 
             Age : 2 
          }, { 
             FirstName : "Beth", 
             LastName : "Doe", 
             Age : 5 
          } 
       ] 
    };
    
    var f = { 
       FirstName : "John", 
       LastName : "Doe", 
       Age : 33, 
       EMailAddresses : [
          "john.doe@gmail.com", 
          "jdoe@hotmail.com"
       ], 
       Children : [ 
          { 
             FirstName : "Sara", 
             LastName : "Doe", 
             Age : 3 
          }, { 
             FirstName : "Bethany", 
             LastName : "Doe", 
             Age : 5 
          } 
       ] 
    };
    
    resultobj = []
    function comp_obj(t1,t2){
    	flag = 1;
    	key1_arr = Object.keys(t1)
    	key2_arr = Object.keys(t2)
    	if(key1_arr.length == key2_arr.length){
    		for(key1 in t1){
    			ty1    = Object.prototype.toString.call(t1[key1])
    			ty2    = Object.prototype.toString.call(t2[key1])
    			if(ty1 == ty2) {
    				if(ty1 == '[object String]' || ty1 == '[object Number]' ){
    					if(t2[key1] != t1[key1]){
    						flag = 0;
    						break;
    					}	
    				}else if(ty1 == '[object Array]'){
    					var result = comp_arr(t1[key1],t2[key1]);
    					console.log(ty1,ty2)
    					if(!result)
    						flag = 0;
    				}else if(ty1  == '[object Object]'){
    					var result = comp_obj(t1[key1],t2[key1])
    					if(!result)
    						flag = 0;
    						
    				}
    			}else{
    				flag = 0;
    				break;	
    			}
    
    		}
    	}else{
    		flag	= 0;
    	}
    	if(flag)
    		return true
    	else
    		return false;
    }
    function comp_arr(a,b){
    	flag = 1;
    	if(a.length == b.length ){
    		for(var i=0,l=a.length;i<l;i++){
    			type1    = Object.prototype.toString.call(a[i])
    			type2    = Object.prototype.toString.call(b[i])
    			if(type1 == type2) {
    				if(type1 == '[object String]' || type1 == '[object Number]' ){
    					if( a[i] != b[i]){
    						flag = 0;
    						break;
    					}	
    				}else if(type1 == '[object Array]'){
    					var result = comp_arr(a[i],b[i]);
    					if(!result)
    						flag = 0;
    				}else if(type1  == '[object Object]'){
    					var result = comp_obj(a[i],b[i])
    					if(!result)
    						flag = 0;
    				}	
    			}else{
    				flag = 0;
    				break;	
    			}
    		}
    	}else
    		 flag = 0;
    	if(flag)
    		return true
    	else
    		return false;
    }
    function create(t,attr,parent_node,innerdata){
    	var dom = document.createElement(t)
    	for(key in attr){
    		dom.setAttribute(key,attr[key])
    	}
    	dom.innerHTML = innerdata;
    	parent_node.appendChild(dom)
    	return dom;
    }
    window.onload = function () {
    	for(key in f){
    		if(!(key in d)) 
    			resultobj.push({'Property_name':key,'f_value':JSON.stringify(f[key]),'d_value':JSON.stringify(d[key])})
    		type1    = Object.prototype.toString.call(f[key])
    		type2    = Object.prototype.toString.call(d[key])
    		if(type1 == type2){
    			if(type1 == '[object String]' || type1 == '[object Number]' ){
    				if(f[key] != d[key])
    					resultobj.push({'Property_name':key,'f_value':JSON.stringify(f[key]),'d_value':JSON.stringify(d[key])})
    			}else if(type1 == '[object Array]'){
    				var result = comp_arr(f[key],d[key]);
    				if(!result)
    					resultobj.push({'Property_name':key,'f_value':JSON.stringify(f[key]),'d_value':JSON.stringify(d[key])})
    			}else if(type1 == '[object Object]'){
    				var result = comp_obj(f[key],d[key])	
    				if(!result)
    					resultobj.push({'Property_name':key,'f_value':JSON.stringify(f[key]),'d_value':JSON.stringify(d[key])})
    			}
    		}else 
    			resultobj.push({'Property_name':key,'f_value':JSON.stringify(f[key]),'d_value':JSON.stringify(d[key])})
    	}
    	var tb = document.getElementById('diff');
    	var s1 = document.getElementById('source1');
    	var s2 = document.getElementById('source2');
    	s1.innerHTML = 'Object 1 :'+ JSON.stringify(f)
    	s2.innerHTML = 'Object 2 :'+JSON.stringify(d)
    	resultobj.forEach(function(data,i){
    			tr_dom = create('tr',{},tb,'')
    			no = create('td',{},tr_dom,i+1)
    			Object.keys(data).forEach(function(tr){
    				td_dom = create('td',{},tr_dom,data[tr])
    			})
    	})
    }
      <html>
        <body>
          <p id="source1"> </p>
          <p id="source2"> </p>
          <p id="source7"> DIFFERENCE TABLE</p>
          <table border=''>
            <thead>
              <th>S.no</th>
              <th>Name Of the Key</th>
              <th>Object1 Value</th>
              <th>Object2 Value</th>
            </thead>
            <tbody id="diff">
    
            </tbody>
          </table>
        </body>
    </html>

    0 讨论(0)
  • 2020-11-29 01:14

    None of the libraries I found were sufficient so I wrote my own AngularJS factory. It compares the objects in both ways and returns only the difference within the same structure.

    /**
     * Diff
     * Original author: Danny Coulombe
     * Creation date: 2016-05-18
     * 
     * Work with objects to find their differences.
     */
    controllers.factory('diff', [function() {
    
        var factory = {
    
            /**
             * Compare the original object with the modified one and return their differences.
             * 
             * @param original: Object
             * @param modified: Object
             * 
             * @return Object
             */
            getDifferences: function(original, modified) {
    
                var type = modified.constructor === Array ? [] : {};
                var result = angular.copy(type);
                var comparisons = [[original, modified, 1], [modified, original, 0]];
    
                comparisons.forEach(function(comparison) {
    
                    angular.forEach(comparison[0], function(value, key) {
    
                        if(result[key] === undefined) {
    
                            if(comparison[1][key] !== undefined && value !==    null && comparison[1][key] !== null && [Object, Array].indexOf(comparison[1][key].constructor) !== -1) {
    
                                result[key] = factory.getDifferences(value, comparison[1][key]);
                            }
                            else if(comparison[1][key] !== value) {
    
                                result[key] = comparison[comparison[2]][key];
                            }
    
                            if(angular.equals(type, result[key])
                            || result[key] === undefined
                            || (
                                comparison[0][key] !== undefined
                                && result[key] !== null
                                && comparison[0][key] !== null
                                && comparison[0][key].length === comparison[1][key].length
                                && result[key].length === 0
                            )) {
                                delete result[key];
                            }
                        }
                    });
                });
    
                return result;
            }
        };
    
        return factory;
    }]);
    
    0 讨论(0)
  • 2020-11-29 01:17

    I recently wrote a module to do this, because I wasn't satisfied with the numerous diffing modules I found (I listed a bunch of the most popular modules and why they weren't acceptable in the readme of my module). Its called odiff: https://github.com/Tixit/odiff . Here's an example:

    var a = [{a:1,b:2,c:3},              {x:1,y: 2, z:3},              {w:9,q:8,r:7}]
    var b = [{a:1,b:2,c:3},{t:4,y:5,u:6},{x:1,y:'3',z:3},{t:9,y:9,u:9},{w:9,q:8,r:7}]
    
    var diffs = odiff(a,b)
    
    /* diffs now contains:
    [{type: 'add', path:[], index: 2, vals: [{t:9,y:9,u:9}]},
     {type: 'set', path:[1,'y'], val: '3'},
     {type: 'add', path:[], index: 1, vals: [{t:4,y:5,u:6}]}
    ]
    */
    
    0 讨论(0)
  • 2020-11-29 01:18

    There is an objectDiff library which allows you to do that. On its demo page you can see a difference between two javascript objects.

    0 讨论(0)
  • 2020-11-29 01:19

    After reviewing the existing answers, I noticed that the https://github.com/flitbit/diff library was not yet listed as a solution.

    From my research, this library seems to be the best in terms of active development, contributions and forks for solving the challenge of diffing objects. This is very handy for creating a diff on the server side and passing the client only the changed bits.

    0 讨论(0)
  • 2020-11-29 01:19

    you can do'it with filter and indexOf

    var first = [ 1, 2, 3, 4, 5 ];
    var second = [ 4, 5, 6 ];
    
    var difference = first.filter(x => second.indexOf(x) === -1);
    console.log(difference);
    
    0 讨论(0)
提交回复
热议问题