This is a question that involves a more plicated way of parison, Thus it's not a duplicate
I've created a JqTree, that when the user changes its tree structure, both "old" JSON
and "new" JSON
structures should be pared, and it should be shown only the values of the JSON
that has been changed.
For example:
[{"name":"node1","id":1,"is_open":true,"children":
[
{"name":"child1","id":2},
{"name":"child2","id":3}
]
}]
After the client has placed child1
under child2
[{"name":"node1","id":1,"is_open":true,"children":
[
{"name":"child2","id":3},
{"name":"child1","id":2}
]
}]
I just would like to pare them and check which values were changed and show them with an alert
, which, in this case, would be:
{"name":"child2","id":3},
{"name":"child1","id":2}
So far I have this tiny code that pares them:
JSON.stringify(object1) === JSON.stringify(object2); //I know it's not too reliable.
But I'm looking for something that checks the "difference" and extracts it from the JSON.
Thanks in advance.
This is a question that involves a more plicated way of parison, Thus it's not a duplicate
I've created a JqTree, that when the user changes its tree structure, both "old" JSON
and "new" JSON
structures should be pared, and it should be shown only the values of the JSON
that has been changed.
For example:
[{"name":"node1","id":1,"is_open":true,"children":
[
{"name":"child1","id":2},
{"name":"child2","id":3}
]
}]
After the client has placed child1
under child2
[{"name":"node1","id":1,"is_open":true,"children":
[
{"name":"child2","id":3},
{"name":"child1","id":2}
]
}]
I just would like to pare them and check which values were changed and show them with an alert
, which, in this case, would be:
{"name":"child2","id":3},
{"name":"child1","id":2}
So far I have this tiny code that pares them:
JSON.stringify(object1) === JSON.stringify(object2); //I know it's not too reliable.
But I'm looking for something that checks the "difference" and extracts it from the JSON.
Thanks in advance.
Share Improve this question edited May 23, 2017 at 11:46 CommunityBot 11 silver badge asked Jul 8, 2015 at 14:23 KyleKyle 1,5782 gold badges20 silver badges49 bronze badges 9- 1 Computing the difference between two data structures is not a simple affair. Here's a related stackexchange question. – Pointy Commented Jul 8, 2015 at 14:24
- @Pointy indeed, but isn't easier to transform them into a different "type", and then pare? if I transform them, for example, into string like stringifying them. I'm sorry if it sounds dumb – Kyle Commented Jul 8, 2015 at 14:27
- Well you can do that, but then you get a string difference; a character-by-character difference, in other words. Now you're faced with the problem of interpreting that result in terms of the data structure, which (as I understand it) is the actual model involved. – Pointy Commented Jul 8, 2015 at 14:35
- @Pointy yeah I see it. What do you suggest? given the fact that my tree won't be more plex that on my example. – Kyle Commented Jul 8, 2015 at 14:39
- 1 You could write a recursive function to walk down the old tree node by node, pare to the new tree, when a difference is found add that node to a collection and at the end alert the collection. – lwalden Commented Jul 8, 2015 at 14:49
1 Answer
Reset to default 8Here you go: http://jsfiddle/musicin3d/cf5ddod1/3/
Edited down version for your no-clicking pleasure:
// Call this function.
// The others are helpers for this one.
function getDiff(a, b){
var diff = (isArray(a) ? [] : {});
recursiveDiff(a, b, diff);
return diff;
}
function recursiveDiff(a, b, node){
var checked = [];
for(var prop in a){
if(typeof b[prop] == 'undefined'){
addNode(prop, '[[removed]]', node);
}
else if(JSON.stringify(a[prop]) != JSON.stringify(b[prop])){
// if value
if(typeof b[prop] != 'object' || b[prop] == null){
addNode(prop, b[prop], node);
}
else {
// if array
if(isArray(b[prop])){
addNode(prop, [], node);
recursiveDiff(a[prop], b[prop], node[prop]);
}
// if object
else {
addNode(prop, {}, node);
recursiveDiff(a[prop], b[prop], node[prop]);
}
}
}
}
}
function addNode(prop, value, parent){
parent[prop] = value;
}
function isArray(obj){
return (Object.prototype.toString.call(obj) === '[object Array]');
}
See the link above for more details. There is a ment that explains some of my assumptions.
This is an example of how to use recursion to solve your problem. If you're not familiar with recursion, I suggest you do some reading. Here's a SO article about it: What is recursion and when should I use it?
Of note:
Using JSON.stringify
like I did is not a good idea. It's convenient for me as the programmer because my program can "look ahead" to see if there's a change down each path, but that es at a cost. I'm already traversing the tree structure to do my work, and JSON.stringify
also traverses the tree structure of every object I send every time I call it. In puter science we call this a worst case scenario of O(n!), less formally referred to as "very slow." A better design would just traverse the entire tree and keep track of how it got to where it was. When it came to a dead end (called a "leaf" node"), it would use this knowledge to add the necessary data structure to the diff
variable all at once. This would mean our program would have to traverse the entire data structure, but our code would be the only thing doing it. So each node would be processed only once.
Still, this should give you an idea of what others were suggesting.