如何在Node.js中合併兩個複雜對象

来源:http://www.cnblogs.com/jaxu/archive/2016/12/26/6221301.html
-Advertisement-
Play Games

通常情況下,在Node.js中我們可以通過underscore的extend或者lodash的merge來合併兩個對象,但是對於像下麵這種複雜的對象,要如何來應對呢? 例如我有以下兩個object: 希望合併之後的結果輸出成下麵這樣: 通過underscore或者lodash現有的方法我們無法實現上 ...


  通常情況下,在Node.js中我們可以通過underscoreextend或者lodashmerge來合併兩個對象,但是對於像下麵這種複雜的對象,要如何來應對呢?

  例如我有以下兩個object:

var obj1 = {
    "name" : "myname",
    "status" : 0,
    "profile": { "sex":"m", "isactive" : true},
    "strarr":["one", "three"],
    "objarray": [
    {
        "id": 1,
        "email": "[email protected]",
        "isactive":true
    },
    {
        "id": 2,
        "email": "[email protected]",
        "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": "[email protected]"
    },
    {
        "id": 3,
        "email": "[email protected]",
        "isactive" : true
    }
    ]
};

  希望合併之後的結果輸出成下麵這樣:

{ name: 'myname',
  status: 1,
  profile: { sex: 'm', isactive: false, city: 'new York' },
  strarr: [ 'one', 'three', 'two' ],
  objarray: 
  [ { id: 1, email: '[email protected]', isactive: false },
   { id: 2, email: '[email protected]', isactive: false },
   { id: 3, email: '[email protected]', 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
}

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


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • SOLID 原則基本概念: 程式設計領域, SOLID (單一功能、開閉原則、里氏替換、介面隔離以及依賴反轉)是由羅伯特·C·馬丁在21世紀早期 引入的記憶術首字母縮略字,指代了面向對象編程和麵向對象設計的五個基本原則。當這些原則被一起應用時,它們使得一個程式員開發一個容易進行軟體維護和擴展的系統變 ...
  • 微服務 軟體架構是一個包含各種組織的系統組織,這些組件包括 Web伺服器, 應用伺服器, 資料庫,存儲, 通訊層), 它們彼此或和環境存在關係。系統架構的目標是解決利益相關者的關註點。 Conway’s law: Organizations which design systems[...] are... ...
  • 在同一個頁面需要同時使用motools和jquery,對於$,發生了衝突,以下是解決的辦法。 ...
  • hasOwnProperty()僅檢索實例不檢索原型,in即檢索實例,又檢索原型 成員嵌套越深,訪問速度越慢,只在必要的情況下使用對象成員。 如果在同一個函數中你要多次讀取同一個對象屬性,最好將它存入一個局部變數。以局部變 量替代屬性,避免多餘的屬性查找帶來性能開銷。 如果在同一個函數中你要多次讀取 ...
  • 1、將所有<script>標簽放在儘可能接近<body>標簽底部的位置,以保證頁面在腳本運行之前完成解析儘量減少對整個頁面下載的影響 2、限制頁面的<script>總數也可以改善性能。每當頁面解析碰到一個<script>標簽時, 緊接著有一段時間用於代碼執 行。最小化這些延遲時間可以改善頁面的整體性 ...
  • 最近在看微信小程式邊看邊寫demo,整體目錄結構是一:app.js,app.json,app.wxss這三個文件必須是放在根目錄下,二、一個小程式有多個頁面組成,其中每個頁面的結構是:page.js,page.json,page.wxml,page.wxss。 這些文件尾碼名都是微信小程式特定的,其 ...
  • 在HTML中,表單是由<form>元素來組成的。在js中,表單對應的則是HTMLFormElement類型。它和其他HTML元素一樣具有相同的預設屬性。下麵是HTMLFormElement獨有的屬性和方法: acceptCharset:伺服器能夠處理的字元集,等價於HTML的accept-chars ...
  • 首先要明白什麼是模糊查詢(廢話又來了),就是根據關鍵字把列表中符合關鍵字的一項或某項羅列出來,也就是要檢查列表的每一項中是否含有關鍵字,因此抽象一下就是一個字元串中是否含有某個字元或者字元串。 以下例子沒有接觸到後臺數據的知識,只是查詢當前表格中每一行所包含的關鍵字。 用到的方法為:string.i ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...