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


Posted in Javascript onDecember 31, 2016

前言

相信大家都知道在通常情况下,在Node.js中我们可以通过underscore的extend或者lodash的merge来合并两个对象,但是对于像下面这种复杂的对象,要如何来应对呢?下面来一起学习学习吧。

Node.js合并两个复杂对象

例如我有以下两个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
}

总结

以上就是这篇文章的全部内容了,文中提到的上述代码在日常工作中很有用,值得大家收藏!希望本文的内容对大家的学习或者工作能带来一定的帮助。

Javascript 相关文章推荐
JSQL 基于客户端的成绩统计实现方法
May 05 Javascript
jquery调用asp.net 页面后台的实现代码
Apr 27 Javascript
服务器端的JavaScript脚本 Node.js 使用入门
Mar 07 Javascript
js中判断对象是否为空的三种实现方法
Dec 23 Javascript
简单谈谈javascript Date类型
Sep 06 Javascript
如何使用Bootstrap的modal组件自定义alert,confirm和modal对话框
Mar 01 Javascript
jQuery插件FusionWidgets实现的Bulb图效果示例【附demo源码下载】
Mar 23 jQuery
微信小程序 动态传参实例详解
Apr 27 Javascript
create-react-app安装出错问题解决方法
Sep 04 Javascript
vue 属性拦截实现双向绑定的实例代码
Oct 24 Javascript
微信小程序外卖选购页实现切换分类与数量加减功能案例
Jan 15 Javascript
vue cli 3.0 搭建项目的图文教程
May 17 Javascript
javascript 闭包详解及简单实例应用
Dec 31 #Javascript
深入理解Angularjs中的$resource服务
Dec 31 #Javascript
BootStrap Fileinput的使用教程
Dec 30 #Javascript
BootStrap Fileinput初始化时的一些参数
Dec 30 #Javascript
bootstrapValidator表单验证插件学习
Dec 30 #Javascript
JS实现类似百叶窗下拉菜单效果
Dec 30 #Javascript
BootStrap实现轮播图效果(收藏)
Dec 30 #Javascript
You might like
PHP详细彻底学习Smarty
2008/03/27 PHP
php实现文件下载(支持中文文名)
2013/12/04 PHP
详解PHP实现支付宝小程序用户授权的工具类
2018/12/25 PHP
用JavaScript实现UrlEncode和UrlDecode的脚本代码
2008/07/23 Javascript
从JavaScript 到 JQuery (1)学习小结
2009/02/12 Javascript
javascript getElementsByClassName函数
2010/04/01 Javascript
ajax上传时参数提交不更新等相关问题
2012/12/11 Javascript
javascript Array.prototype.slice的使用示例
2013/11/14 Javascript
jquery中event对象属性与方法小结
2013/12/18 Javascript
jQuery使用attr()方法同时设置多个属性值用法实例
2015/03/26 Javascript
关于动态执行代码(js的Eval)实例详解
2016/08/15 Javascript
原生js实现可爱糖果数字时间特效
2016/12/30 Javascript
js中apply和Math.max()函数的问题及区别介绍
2018/03/27 Javascript
jQuery 导航自动跟随滚动的实现代码
2018/05/30 jQuery
Vue实现简单分页器
2018/12/29 Javascript
js全屏事件fullscreenchange 实现全屏、退出全屏操作
2019/09/17 Javascript
解决基于 keep-alive 的后台多级路由缓存问题
2020/12/23 Javascript
[31:47]夜魇凡尔赛茶话会 第三期01:选手知多少
2021/03/11 DOTA
Python ldap实现登录实例代码
2016/09/30 Python
python/sympy求解矩阵方程的方法
2018/11/08 Python
Django利用cookie保存用户登录信息的简单实现方法
2019/05/27 Python
PyTorch预训练的实现
2019/09/18 Python
Python 基于wxpy库实现微信添加好友功能(简洁)
2019/11/29 Python
利用python在excel中画图的实现方法
2020/03/17 Python
h5使用canvas画布实现手势解锁
2019/01/04 HTML / CSS
Currentbody澳大利亚:美容仪专家
2019/11/11 全球购物
PHP数据运算类型都有哪些
2013/11/05 面试题
仓库班组长岗位职责
2013/12/12 职场文书
生产车间班组长岗位职责
2014/01/06 职场文书
运动会演讲稿300字
2014/08/25 职场文书
单位法人授权委托书范本
2014/10/09 职场文书
离婚协议书范本
2015/01/26 职场文书
学校艾滋病宣传活动总结
2015/05/09 职场文书
Nginx如何配置Http、Https、WS、WSS的方法步骤
2021/05/11 Servers
Mysql systemctl start mysqld报错的问题解决
2021/06/03 MySQL
Python中with上下文管理协议的作用及用法
2022/03/18 Python