通常情况下,在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
}

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

如何在Node.js中合并两个复杂对象的更多相关文章

  1. 如何在node.js中使用neo4j

    本章中你将会学到如何在node.js中使用neo4j图形数据库. 当你想存储或者查询和数据紧密关联的数据的时候,图形数据库很有用. neo4j是一个可有效存储,处理和查询你数据模型中紧密相连的元素的数 ...

  2. JavaScript中的两种全局对象

    这里总结的东西特别适合先学习c/c++, Java这类标准语言再学JS的童鞋们看,因为JS在程序执行之前就会初始化一个全局对象,这个全局对象到底是什么是跟JS程序运行环境有关的. 根据JavaScri ...

  3. Node.js中的Session,不要觉得简单哦。

    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,博客地址为http://www.cnblogs.com/jasonnode/ .学习网站上有对应 ...

  4. 在node.js中使用COOKIE

    node.js中如何向客户端发送COOKIE呢?有如下两个方案: 一.使用response.writeHead,代码示例: //设置过期时间为一分钟 var today = new Date(); v ...

  5. 初步揭秘node.js中的事件

    当你学习node.js的时候,Events是一个非常重要的需要理解的事情.非常多的Node对象触发事件,你能在文档API中找到很多例子.但是关于如何写自己的事件和监听,你可能还不太清楚.如果你不了解, ...

  6. 在Node.js中使用RabbitMQ系列二 任务队列

    在上一篇文章在Node.js中使用RabbitMQ系列一 Hello world我有使用一个任务队列,不过当时的场景是将消息发送给一个消费者,本篇文章我将讨论有多个消费者的场景. 其实,任务队列最核心 ...

  7. node.js中stream流中可读流和可写流的使用

    node.js中的流 stream 是处理流式数据的抽象接口.node.js 提供了很多流对象,像http中的request和response,和 process.stdout 都是流的实例. 流可以 ...

  8. node.js中path路径模块的使用

    path模块是node.js中处理路径的核心模块.可以很方便的处理关于文件路径的问题. join() 将多个参数值合并成一个路径 const path = require('path'); conso ...

  9. node.js中fs文件系统模块的使用

    node.js中为我们提供了fs文件系统模块,实现对文件或目录的创建,修改和删除等操作. fs模块中,所有的方法分为同步和异步两种实现. 有 sync 后缀的方法为同步方法,没有 sync 后缀的方法 ...

随机推荐

  1. 使用HEXO快速建站

    先安好npm,请参照:http://max.cszi.com/archives/482 打开网站:https://hexo.io/   npm install hexo-cli -g hexo ini ...

  2. 入园记------我的DBA之路

    今天周一拖着疲惫的身躯 11点才离开公司,回到家估计写完这篇博客就要17号了. 一个人走在回家的路上,很黑,突然很多感触,一个人在北京拼搏,不敢停止学习的脚步,因为只要停下来就会感觉到孤独. 回顾一下 ...

  3. 一文搞懂HMM(隐马尔可夫模型)

    什么是熵(Entropy) 简单来说,熵是表示物质系统状态的一种度量,用它老表征系统的无序程度.熵越大,系统越无序,意味着系统结构和运动的不确定和无规则:反之,,熵越小,系统越有序,意味着具有确定和有 ...

  4. ABP源码分析三十六:ABP.Web.Api

    这里的内容和ABP 动态webapi没有关系.除了动态webapi,ABP必然是支持使用传统的webApi.ABP.Web.Api模块中实现了一些同意的基础功能,以方便我们创建和使用asp.net w ...

  5. hibernate与Struts框架结合编写简单针对修改练习

    失败页面fail.jsp <%@ page language="java" contentType="text/html; charset=UTF-8" ...

  6. Atitit zxing二维码qr码识别解析

    Atitit zxing二维码qr码识别解析 1.1. qr码识别解析 by zxing1 1.2. 解码lib:qrcode.jar  2 1.3. atitit.二维码生成总结java zxing ...

  7. js倒计时-倒计输入的时间

    计算指定时间到指定时间之间相差多少天.时.分.秒. 节日.活动.商城常用. 原理: 主要使用到时间戳,也就是从1970 年 1 月 1 日 到指定时间的毫秒数. 1. 求出毫秒差 :当两个时间直接进行 ...

  8. img.width一直是0的问题--记录(二)

    var img=new Image(); img.src="图片路径"; 然后调用 img.width img.height 你会发现值是0: 这是因为页面在加载的时候图片是最后的 ...

  9. SQL Server-聚焦强制索引查询条件和Columnstore Index(九)

    前言 本节我们再来穿插讲讲索引知识,后续再讲数据类型中的日期类型,简短的内容,深入的理解,Always to review the basics. 强制索引查询条件 前面我们也讲了一点强制索引查询的知 ...

  10. context:component-scan" 的前缀 "context" 未绑定。

    SpElUtilTest.testSpELLiteralExpressiontestSpELLiteralExpression(cn.zr.spring.spel.SpElUtilTest)org.s ...