如何在Node.js中合并两个复杂对象

简介:

通常情况下,在Node.js中我们可以通过underscoreextend或者lodashmerge来合并两个对象,但是对于像下面这种复杂的对象,要如何来应对呢?

  例如我有以下两个object:

复制代码
var obj1 = {
    "name" : "myname",
    "status" : 0,
    "profile": { "sex":"m", "isactive" : true},
    "strarr":["one", "three"],
    "objarray": [
    {
        "id": 1,
        "email": "a1@me.com",
        "isactive":true
    },
    {
        "id": 2,
        "email": "a2@me.com",
        "isactive":false
    }
    ]
};

var obj2 = {
    "name" : "myname",
    "status" : 1,
    "newfield": 1,
    "profile": { "isactive" : false,  "city": "new York"},
    "strarr":["two"],
    "objarray": [
    {
        "id": 1,
        "isactive":false
    },
    {
        "id": 2,
        "email": "a2modified@me.com"
    },
    {
        "id": 3,
        "email": "a3new@me.com",
        "isactive" : true
    }
    ]
};
复制代码

  希望合并之后的结果输出成下面这样:

复制代码
{ name: 'myname',
  status: 1,
  profile: { sex: 'm', isactive: false, city: 'new York' },
  strarr: [ 'one', 'three', 'two' ],
  objarray: 
  [ { id: 1, email: 'a1@me.com', isactive: false },
   { id: 2, email: 'a2modified@me.com', isactive: false },
   { id: 3, email: 'a3new@me.com', isactive: true } ],
newfield: 1 }
复制代码

   通过underscore或者lodash现有的方法我们无法实现上述结果,那只能自己写代码来实现了。

复制代码
function mergeObjs(def, obj) {
  if (!obj) {
    return def;
  } else if (!def) {
    return obj;
  }

  for (var i in obj) {
    // if its an object
    if (obj[i] != null && obj[i].constructor == Object)
    {
      def[i] = mergeObjs(def[i], obj[i]);
    }
    // if its an array, simple values need to be joined.  Object values need to be remerged.
    else if(obj[i] != null && (obj[i] instanceof Array) && obj[i].length > 0)
    {
      // test to see if the first element is an object or not so we know the type of array we're dealing with.
      if(obj[i][0].constructor == Object)
      {
        var newobjs = [];
        // create an index of all the existing object IDs for quick access.  There is no way to know how many items will be in the arrays.
        var objids = {}
        for(var x= 0, l= def[i].length ; x < l; x++ )
        {
          objids[def[i][x].id] = x;
        }

        // now walk through the objects in the new array
        // if the ID exists, then merge the objects.
        // if the ID does not exist, push to the end of the def array
        for(var x= 0, l= obj[i].length; x < l; x++)
        {
          var newobj = obj[i][x];
          if(objids[newobj.id] !== undefined)
          {
            def[i][x] = mergeObjs(def[i][x],newobj);
          }
          else {
            newobjs.push(newobj);
          }
        }

        for(var x= 0, l = newobjs.length; x<l; x++) {
          def[i].push(newobjs[x]);
        }
      }
      else {
        for(var x=0; x < obj[i].length; x++)
        {
          var idxObj = obj[i][x];
          if(def[i].indexOf(idxObj) === -1) {
             def[i].push(idxObj);
          }
        }
      }
    }
    else
    {
      def[i] = obj[i];
    }
  }
  return def;}
复制代码

   将上述代码稍作改进,我们可以实现在合并过程中将Number类型的值自动相加。

复制代码
function merge(def, obj) {
    if (!obj) {
        return def;
    }
    else if (!def) {
        return obj;
    }

    for (var i in obj) {
        // if its an object
        if (obj[i] != null && obj[i].constructor == Object)
        {
            def[i] = merge(def[i], obj[i]);
        }
        // if its an array, simple values need to be joined.  Object values need to be re-merged.
        else if(obj[i] != null && (obj[i] instanceof Array) && obj[i].length > 0)
        {
            // test to see if the first element is an object or not so we know the type of array we're dealing with.
            if(obj[i][0].constructor == Object)
            {
                var newobjs = [];
                // create an index of all the existing object IDs for quick access.  There is no way to know how many items will be in the arrays.
                var objids = {}
                for(var x= 0, l= def[i].length ; x < l; x++ )
                {
                    objids[def[i][x].id] = x;
                }

                // now walk through the objects in the new array
                // if the ID exists, then merge the objects.
                // if the ID does not exist, push to the end of the def array
                for(var x= 0, l= obj[i].length; x < l; x++)
                {
                    var newobj = obj[i][x];
                    if(objids[newobj.id] !== undefined)
                    {
                        def[i][x] = merge(def[i][x],newobj);
                    }
                    else {
                        newobjs.push(newobj);
                    }
                }

                for(var x= 0, l = newobjs.length; x<l; x++) {
                    def[i].push(newobjs[x]);
                }
            }
            else {
                for(var x=0; x < obj[i].length; x++)
                {
                    var idxObj = obj[i][x];
                    if(def[i].indexOf(idxObj) === -1) {
                        def[i].push(idxObj);
                    }
                }
            }
        }
        else
        {
            if (isNaN(obj[i]) || i.indexOf('_key') > -1){
                def[i] = obj[i];
            }
            else{
                def[i] += obj[i];
            }
        }
    }
    return def;
}
复制代码

  例如有以下两个对象:

复制代码
var data1 = {
    "_id" : "577327c544bd90be508b46cc",
    "channelId_info" : [
    {
        "channelId_key" : "0",
        "secondLevel_group" : [
        {
            "secondLevel_key" : "568cc36c44bd90625a045c60",
            "sender_group" : [
            {
                "sender_key" : "577327c544bd90be508b46cd",
                "sender_sum" : 40.0
            }
            ],
            "senders_sum" : 40.0
        }
        ],
        "channelId_sum" : 40.0
    }
    ],
    "car_sum" : 40.0
};

var data2 = {
    "_id" : "577327c544bd90be508b46cc",
    "channelId_info" : [
    {
        "channelId_key" : "0",
        "secondLevel_group" : [
        {
            "secondLevel_key" : "568cc36c44bd90625a045c60",
            "sender_group" : [
            {
                "sender_key" : "577327c544bd90be508b46cd",
                "sender_sum" : 20.0
            },
            {
                "sender_key" : "5710bcc7e66620fd4bc0914f",
                "sender_sum" : 5.0
            }
            ],
            "senders_sum" : 25.0
        },
        {
            "secondLevel_key" : "55fbeb4744bd9090708b4567",
            "sender_group" : [
            {
                "sender_key" : "5670f993a2f5dbf12e73b763",
                "sender_sum" : 10.0
            }
            ],
            "senders_sum" : 10.0
        }
        ],
        "channelId_sum" : 35.0
    },
    {
        "channelId_key" : "1",
        "secondLevel_group" : [
        {
            "secondLevel_key" : "568cc36c44bd90625a045c60",
            "sender_group" : [
            {
                "sender_key" : "577327c544bd90be508b46cd",
                "sender_sum" : 20.0
            }
            ],
            "senders_sum" : 20.0
        }
        ],
        "channelId_sum" : 20.0
    }
    ],
    "car_sum" : 55.0
};
复制代码

  合并之后的结果如下:

复制代码
{
    "_id": "577327c544bd90be508b46cc",
    "channelId_info": [
        {
            "channelId_key": "0",
            "secondLevel_group": [
                {
                    "secondLevel_key": "568cc36c44bd90625a045c60",
                    "sender_group": [
                        {
                            "sender_key": "577327c544bd90be508b46cd",
                            "sender_sum": 60
                        },
                        {
                            "sender_key": "5710bcc7e66620fd4bc0914f",
                            "sender_sum": 5
                        }
                    ],
                    "senders_sum": 65
                },
                {
                    "secondLevel_key": "55fbeb4744bd9090708b4567",
                    "sender_group": [
                        {
                            "sender_key": "5670f993a2f5dbf12e73b763",
                            "sender_sum": 10
                        }
                    ],
                    "senders_sum": 10
                }
            ],
            "channelId_sum": 75
        },
        {
            "channelId_key": "1",
            "secondLevel_group": [
                {
                    "secondLevel_key": "568cc36c44bd90625a045c60",
                    "sender_group": [
                        {
                            "sender_key": "577327c544bd90be508b46cd",
                            "sender_sum": 20
                        }
                    ],
                    "senders_sum": 20
                }
            ],
            "channelId_sum": 20
        }
    ],
    "car_sum": 95
}
复制代码

  上述代码在日常工作中很有用,值得收藏!


本文转自Jaxu博客园博客,原文链接:http://www.cnblogs.com/jaxu/p/6221301.html,如需转载请自行联系原作者


相关文章
|
1月前
|
JavaScript 前端开发
JavaScript Date(日期) 对象
JavaScript Date(日期) 对象
38 2
|
5天前
|
Web App开发 JavaScript 前端开发
如何确保 Math 对象的方法在不同的 JavaScript 环境中具有一致的精度?
【10月更文挑战第29天】通过遵循标准和最佳实践、采用固定精度计算、进行全面的测试与验证、避免隐式类型转换以及持续关注和更新等方法,可以在很大程度上确保Math对象的方法在不同的JavaScript环境中具有一致的精度,从而提高代码的可靠性和可移植性。
|
1天前
|
JavaScript 前端开发
如何在 JavaScript 中使用 __proto__ 实现对象的继承?
使用`__proto__`实现对象继承时需要注意原型链的完整性和属性方法的正确继承,避免出现意外的行为和错误。同时,在现代JavaScript中,也可以使用`class`和`extends`关键字来实现更简洁和直观的继承语法,但理解基于`__proto__`的继承方式对于深入理解JavaScript的面向对象编程和原型链机制仍然具有重要意义。
|
5天前
|
JavaScript 前端开发 图形学
JavaScript 中 Math 对象常用方法
【10月更文挑战第29天】JavaScript中的Math对象提供了丰富多样的数学方法,涵盖了基本数学运算、幂运算、开方、随机数生成、极值获取以及三角函数等多个方面,为各种数学相关的计算和处理提供了强大的支持,是JavaScript编程中不可或缺的一部分。
|
29天前
|
存储 JavaScript 前端开发
JavaScript 对象的概念
JavaScript 对象的概念
35 4
|
27天前
|
缓存 JavaScript 前端开发
JavaScript中数组、对象等循环遍历的常用方法介绍(二)
JavaScript中数组、对象等循环遍历的常用方法介绍(二)
29 1
|
28天前
|
存储 JavaScript 前端开发
js中函数、方法、对象的区别
js中函数、方法、对象的区别
15 2
|
30天前
|
JavaScript 前端开发 Unix
Node.js 全局对象
10月更文挑战第5天
21 2
|
1月前
|
存储 JavaScript 前端开发
js中的对象
js中的对象
18 3
|
1月前
|
JavaScript 前端开发
JavaScript Math(算数) 对象
JavaScript Math(算数) 对象
20 4