通常情况下,在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. Eclipse使用Git教程

    A:点击Window--->Show view--->other..--->Git Repositories--->[OK] B:克隆码云上的代码仓库 C:选择对应目录存储你的 ...

  2. ASP.NET MVC 5 系列 学习笔记 目录 (持续更新...)

    前言: 记得当初培训的时候,学习的还是ASP.NET,现在回想一下,图片水印.统计人数.过滤器....HttpHandler是多么的经典! 不过后来接触到了MVC,便立马爱上了它.Model-View ...

  3. Linux实战教学笔记03:操作系统发展历程及系统版本选择

    标签(空格分隔): Linux实战教学笔记-陈思齐 第1章 Linux简介 1.1 什么是操作系统? 简单讲:操作系统就是一个人与计算机硬件的中介. 操作系统,英文名称Operating System ...

  4. MzBlog分析

    早上衣明志 在QQ群里说他的博客开源了,地址在 https://github.com/qihangnet/MZBlog,基于NancyFX和MongoDB开发的.博客内容需要使用 MarkDown 进 ...

  5. .NET基础拾遗(6)ADO.NET与数据库开发基础

    Index : (1)类型语法.内存管理和垃圾回收基础 (2)面向对象的实现和异常的处理 (3)字符串.集合与流 (4)委托.事件.反射与特性 (5)多线程开发基础 (6)ADO.NET与数据库开发基 ...

  6. 用C表达面向对象语言的机制——C#版

    PS:本文PDF版在这里(格式更好看一些).最新的源代码请在本页面文末下载,PDF中的链接不是最新的. 用C表达面向对象语言的机制——C#版 我一直认为,面向对象语言是对面向过程语言的封装.如果是这样 ...

  7. ERROR ITMS-90167: "No .app bundles found in the package"错误

    ERROR ITMS-90167: "No .app bundles found in the package" 出现如上错误请查检以下2个方向: 1.macOS Sierra 1 ...

  8. JMeter压力测试

    Apache JMeter是Apache组织开发的基于Java的压力测试工具.用于对软件做压力测试,它最初被设计用于Web应用测试但后来扩展到其他测试领域. 它可以用于测试静态和动态资源例如静态文件. ...

  9. 存储程序(1)——MYSQL

    MySQL支持把几种对象存放在服务器端供以后使用.这几种对象有一些可以根据情况通过程序代码调用,有一些会在数据表被修改时自动执行,还有一些可以在预定时刻自动执行.它们包括以下几种: 1.存储函数(st ...

  10. MVC5 网站开发之三 数据存储层功能实现

    数据存储层在项目Ninesky.DataLibrary中实现,整个项目只有一个类Repository.   目录 奔跑吧,代码小哥! MVC5网站开发之一 总体概述 MVC5 网站开发之二 创建项目 ...