如何在Node.js中合并两个复杂对象
通常情况下,在Node.js中我们可以通过underscore的extend或者lodash的merge来合并两个对象,但是对于像下面这种复杂的对象,要如何来应对呢?
例如我有以下两个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中合并两个复杂对象的更多相关文章
- 如何在node.js中使用neo4j
本章中你将会学到如何在node.js中使用neo4j图形数据库. 当你想存储或者查询和数据紧密关联的数据的时候,图形数据库很有用. neo4j是一个可有效存储,处理和查询你数据模型中紧密相连的元素的数 ...
- JavaScript中的两种全局对象
这里总结的东西特别适合先学习c/c++, Java这类标准语言再学JS的童鞋们看,因为JS在程序执行之前就会初始化一个全局对象,这个全局对象到底是什么是跟JS程序运行环境有关的. 根据JavaScri ...
- Node.js中的Session,不要觉得简单哦。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,博客地址为http://www.cnblogs.com/jasonnode/ .学习网站上有对应 ...
- 在node.js中使用COOKIE
node.js中如何向客户端发送COOKIE呢?有如下两个方案: 一.使用response.writeHead,代码示例: //设置过期时间为一分钟 var today = new Date(); v ...
- 初步揭秘node.js中的事件
当你学习node.js的时候,Events是一个非常重要的需要理解的事情.非常多的Node对象触发事件,你能在文档API中找到很多例子.但是关于如何写自己的事件和监听,你可能还不太清楚.如果你不了解, ...
- 在Node.js中使用RabbitMQ系列二 任务队列
在上一篇文章在Node.js中使用RabbitMQ系列一 Hello world我有使用一个任务队列,不过当时的场景是将消息发送给一个消费者,本篇文章我将讨论有多个消费者的场景. 其实,任务队列最核心 ...
- node.js中stream流中可读流和可写流的使用
node.js中的流 stream 是处理流式数据的抽象接口.node.js 提供了很多流对象,像http中的request和response,和 process.stdout 都是流的实例. 流可以 ...
- node.js中path路径模块的使用
path模块是node.js中处理路径的核心模块.可以很方便的处理关于文件路径的问题. join() 将多个参数值合并成一个路径 const path = require('path'); conso ...
- node.js中fs文件系统模块的使用
node.js中为我们提供了fs文件系统模块,实现对文件或目录的创建,修改和删除等操作. fs模块中,所有的方法分为同步和异步两种实现. 有 sync 后缀的方法为同步方法,没有 sync 后缀的方法 ...
随机推荐
- Android开发案例 – 在AbsListView中使用倒计时
在App中, 有多种多样的倒计时需求, 比如: 在单View上, 使用倒计时, 如(如图-1) 在ListView(或者GridView)的ItemView上, 使用倒计时(如图-2) 图-1 图-2 ...
- ASP.NET Aries JSAPI 文档说明:AR.DataGrid
AR.DataGrid 文档 用法: <body> <table id="dg"></table> </body> </htm ...
- C++模板编程:如何使非通用的模板函数实现声明和定义分离
我们在编写C++类库时,为了隐藏实现,往往只能忍痛舍弃模版的强大特性.但如果我们只需要有限的几个类型的模版实现,并且不允许用户传入其他类型时,我们就可以将实例化的代码放在cpp文件中实现了.然而,当我 ...
- es6之let和const
在javascript中,我们都知道使用var来声明变量.javascript是函数级作用域,函数内可以访问函数外的变量,函数外不能访问函数内的变量. 函数级作用域会导致一些问题就是某些代码块内的变量 ...
- GDB 多线程调试:只停止断点的线程,其他线程任然执行; 或只运行某些线程 其他线程中断
多线程调试之痛 调试器(如VS2008和老版GDB)往往只支持all-stop模式,调试多线程程序时,如果某个线程断在一个断点上,你的调试器会让整个程序freeze,直到你continue这个线程,程 ...
- salesforce 零基础学习(五十四)常见异常友好消息提示
异常或者error code汇总:https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_calls_con ...
- 牛逼的css3:动态过渡与图形变换
写css3的属性的时候,最好加上浏览器内核标识,进行兼容. -ms-transform:scale(2,4); /* IE 9 */ -moz-transform:scale(2,4); /* Fir ...
- Vue1.0 的技术栈
vuejs概述 Vue.js是用于构建交互式的Web界面的库.它提供了MVVM数据绑定和一个可组合的组件系统,具有简单.灵活的API. 结合node.js 可以实现前后端开发从物理上的分离.使前端负责 ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(52)-美化EasyUI皮肤和图标
系列目录 我很久以前就想更新系统的皮肤功能,Easyui 自带的皮肤已经无法满足客户的审美. 皮肤颜色来源于AdminLTE系统.我的颜色全部都这里取的.,所以一共取了11个颜色.1个皮肤=2个ban ...
- geotrellis使用(二十七)栅格数据色彩渲染
目录 前言 复杂原因及思路分析 实现过程 总结 一.前言 今天我们来研究一下这个看似简单的问题,在地理信息系统中颜色渲染应当是最基本的操作和功能,比如我们将一幅Landsat数据拖拽到A ...