【问题标题】:how to get only the "changed" values from two JSON objects如何仅从两个 JSON 对象中获取“更改”的值
【发布时间】:2015-09-26 12:48:07
【问题描述】:

这是一个比较复杂的问题,所以不是重复的

我创建了一个JqTree,当用户更改其树结构时,“旧”JSON 和“新”JSON 结构都应该进行比较,并且应该只显示JSON 已更改。

例如:

[{"name":"node1","id":1,"is_open":true,"children":
    [
      {"name":"child1","id":2},
      {"name":"child2","id":3}
    ]
}]

客户端将child1置于child2下之后

[{"name":"node1","id":1,"is_open":true,"children":
  [
    {"name":"child2","id":3},
    {"name":"child1","id":2}
  ]
}]

我只想比较它们并检查更改了哪些值并用alert 显示它们,在这种情况下,它将是:

{"name":"child2","id":3},
{"name":"child1","id":2}

到目前为止,我有一个比较它们的小代码:

JSON.stringify(object1) === JSON.stringify(object2); //我知道不太靠谱。

但我正在寻找检查“差异”并从 JSON 中提取它的东西。

提前致谢。

【问题讨论】:

  • 计算两个数据结构之间的差异并不是一件简单的事情。 Here's a related stackexchange question.
  • @Pointy 确实如此,但是将它们转换为不同的“类型”并进行比较不是更容易吗?例如,如果我将它们转换为字符串,例如将它们串起来。如果听起来很愚蠢,我很抱歉
  • 好吧,你可以这样做,但你会得到一个字符串差异;换句话说,逐个字符的差异。现在您面临着根据数据结构解释结果的问题,(据我了解)是所涉及的实际模型。
  • @Pointy 是的,我明白了。你有什么建议?考虑到我的树不会比我的例子更复杂。
  • 您可以编写一个递归函数,逐个节点遍历旧树,与新树进行比较,当发现差异时将该节点添加到集合中,并在最后提醒集合。

标签: javascript jquery json


【解决方案1】:

给你: http://jsfiddle.net/musicin3d/cf5ddod1/3/

为您的无点击乐趣编辑了版本:

// 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]');
}

有关详细信息,请参阅上面的链接。有一条评论解释了我的一些假设。

这是一个如何使用递归来解决问题的示例。如果您不熟悉递归,我建议您阅读一下。这是一篇关于它的SO文章: What is recursion and when should I use it?

注意:
像我一样使用JSON.stringify 不是一个好主意。作为程序员,这对我来说很方便,因为我的程序可以“向前看”以查看每条路径是否有变化,但这是有代价的。我已经遍历tree structure 来完成我的工作,并且JSON.stringify 遍历了我发送的每个对象的树结构每次我调用它。在计算机科学中,我们称之为 O(n!) 的最坏情况,不太正式地称为“非常慢”。更好的设计将遍历整个树并跟踪它是如何到达它的位置的。当它走到一个死胡同(称为“叶”节点“)时,它会利用这些知识一次性将必要的数据结构添加到diff 变量中。这意味着我们的程序将不得不遍历整个数据结构,但我们的代码将是唯一这样做的东西。所以每个节点只会被处理一次。

不过,这应该让您了解其他人的建议。

【讨论】:

  • 另外值得指出的是:如果数组的顺序发生变化,那将显示为不同。
  • 令人惊叹的作品,这是艺术,感谢您提供了这个奇妙的例子,我将把它分解看看它是如何工作的
猜你喜欢
  • 2020-02-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多