简体   繁体   English

如何使用Lodash比较和发现两个复杂对象的差异?

[英]How to use Lodash to compare and find difference for two complex objects?

I'm trying to learn Lodash right now because I think it could help a lot with my current project. 我现在正在尝试学习Lodash,因为我认为这对我当前的项目可能会有很大帮助。 However, I have an issue that I can't figure out how to solve, and, since I'm a Lodash rookie, I thought I'd post something to see if I could get some guidance. 但是,我有一个我无法解决的问题,而且,由于我是Lodash的新秀,因此我认为我会发布一些内容,看看是否可以得到一些指导。

I have two complex objects (see the structure below) – made using angular.copy(original, copy) (my app is, obviously, an Angular app). 我有两个复杂的对象(请参见下面的结构)–使用angular.copy(original,copy)制成(我的应用程序显然是Angular应用程序)。

After the copy, both 复制后,两者

original and copy =
{
    name: 'name',
    date: 'date',
    rows: [  // array of objects
        {
            // this is row 1
            columns: [  // array of objects
                {
                    // this is column 1
                    widgets: [  // array of objects
                        {
                            // this is 1 widget in this column
                            createdDate: 'createdDate1',
                            widgetName: 'widgetName1',
                            widgetParameters: [  // array of objects
                                { parameterName: 'parameterName1', parameterValue: 'parameterValue1' },
                                { parameterName: 'parameterName2', parameterValue: 'parameterValue2' },
                                { parameterName: 'parameterName3', parameterValue: 'parameterValue3' }
                            ]
                        }
                    ]
                },
                {
                    // this is column 2
                    widgets: [
                        {
                            // this is 1 widget in this column
                            createdDate: 'createdDate2',
                            widgetName: 'widgetName2',
                            widgetParameters: [  // array of objects
                                { parameterName: 'parameterName1a', parameterValue: 'parameterValue1a' },
                                { parameterName: 'parameterName2a', parameterValue: 'parameterValue2a' }
                            ]
                        },
                        {
                            // this is 2 widget in this column
                            // ...
                        }
                    ]
                },
                {
                    // this is column 3
                    widgets: [
                        {
                            // this is 1 widget in this column
                            createdDate: 'createdDate3',
                            widgetName: 'widgetName3',
                            widgetParameters: [  // array of objects
                                { parameterName: 'parameterName1b', parameterValue: 'parameterValue1a' }
                            ]
                        },
                        {
                            // this is 2 widget in this column
                            // ...
                        },
                        {
                            // this is 3 widget in this column
                            // ...
                        }
                    ]
                }
            ]  // end columns array
        },
        {
            // this is row 2
            // ... same structure as above with columns, widgets, widgetParameters
        }
    ]  // end rows array
}

After some further processing and changing of property values, I now need to re-sync some of the properties (not all of them) in the copy object back into the original object. 经过一些进一步的处理和属性值的更改后,我现在需要将复制对象中的某些属性(不是全部)重新同步回原始对象。 Specifically, I need to go thru the entire copy object, find all “widgets”, get the “widgetName” value and the complete “widgetParameters” collection from the widget, then go thru the entire original object, find the exact matching “widget”, and update the matching widget's “widgetName” and “widgetParameters” with the values from the copy object. 具体来说,我需要遍历整个副本对象,找到所有“小部件”,从小部件中获取“ widgetName”值和完整的“ widgetParameters”集合,然后遍历整个原始对象,找到与之完全匹配的“ widget” ,并使用复制对象中的值更新匹配的小部件的“ widgetName”和“ widgetParameters”。

I've got it working with a brute force approach with lots of forEach'ing (see below), but I'm thinking there is probably a more elegant and efficient way in Lodash to do what I'm trying to do. 我已经使用蛮力方法进行了很多努力(请参阅下文),但是我认为Lodash中可能有一种更优雅,更有效的方法来完成我想做的事情。

// brute force it
angular.forEach(copy.rows, function (row) {
    angular.forEach(row.columns, function (column) {
        angular.forEach(column.widgets, function (widget) {
            var widgetName = widget.widgetName;
            var createdDate = widget.createdDate;
            var widgetParameters = widget.widgetParameters;

            angular.forEach(original.rows, function (row1) {
                angular.forEach(row1.columns, function (column1) {
                    angular.forEach(column1.widgets, function (widget1) {

                        if ((widgetName === widget1.widgetName) && (createdDate === widget1.createdDate))
                        {
                            widget1.widgetName = widgetName;
                            angular.copy(widgetParameters, widget1.widgetParameters);
                        }

                    });
                });
            });

        });
    });
});

Any thoughts, help, ideas, etc.? 有任何想法,帮助,想法等吗?

Thanks! 谢谢!

I have had great success with the JavaScript-based deep-diff utility. 基于JavaScript的Deep-diff实用程序取得了巨大的成功。 For example: 例如:

// this would be a node.js way to require it, or you could use the DeepDiff object in the browser's global window object
var diff = require('deep-diff').diff;
var differences = diff(original, copy);

If you wanted to apply some changes at the browser level, you could iterate over the changes (differences) and do something like this for each difference received: 如果您想在浏览器级别应用一些更改,则可以遍历更改(差异)并对接收到的每个差异执行以下操作:

DeepDiff.applyChange(original, {}, difference);

I don't know of an elegant and easy way to do this in Lodash, without rebuilding the functionality of the deep-diff library. 我不知道在Lodash中没有重新构建deep-diff库功能的优雅而简单的方法。

What you could do is build the smaller object that contains only the things you want to keep, let's call it diffObject , so then you only need to do: 您可以做的是构建一个较小的对象,该对象仅包含要保留的内容,我们将其diffObject ,因此您只需要执行以下操作:

// Puts the diff back into the original object
_.merge( originalObject, diffObject );

Now to construct such diff object you may still need to go through all your object, or have some clever recursive building function that keeps track of the path it has gone through and all. 现在,要构造这样的diff对象,您可能仍然需要遍历所有对象,或者具有一些巧妙的递归构建函数来跟踪其经过的路径以及所有路径。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM