如何优化包含对象阵列的两个对象的合并

时间:2012-10-07 17:23:47

标签: javascript node.js

我需要在一个将被大量使用的代码路径中合并两个对象。代码有效,但我担心它的速度不够优化,我正在寻找任何改进/替换我想出的建议。我最初开始在这个问题的最后处理一个例子:How can I merge properties of two JavaScript objects dynamically?。该解决方案适用于简单对象。但是,我的需求有一个扭曲,这是性能问题的来源。我需要能够支持数组

  1. 一组简单值将在新对象中查找值并将其添加到现有对象的末尾,并且
  2. 一个对象数组将合并对象(基于id属性的存在)或将新对象(id属性不存在的对象)推送到现有数组的末尾。
  3. 我不需要函数/方法克隆,我不关心hasOwnProperty,因为对象在合并后会返回JSON字符串。

    任何建议都可以帮助我从表演中获取最后一次表演。非常感谢。

    var utils = require("util");
    
    function mergeObjs(def, obj) {
      if (typeof obj == 'undefined') {
        return def;
      } else if (typeof def == 'undefined') {
        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 && utils.isArray(obj[i]) && 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;}
    

    要合并的对象样本:

    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
                    }
                ]
            };
    

    合并后,这个console.log(mergeObjs(obj1,obj2))应该产生这个:

    { 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 }
    

2 个答案:

答案 0 :(得分:3)

我会查看:https://github.com/bestiejs/lodash

_.merge不在“优化”功能列表中,但这是经过测试的战斗,战斗硬化。他还有一个性能套件,可以询问您如何为perf套件做出贡献,以便了解merge实现。

https://github.com/bestiejs/lodash/blob/master/lodash.js#L1677-1738

编辑:顺便说一句,我不会过早地优化。我会在你的用例中看到这实际上是否存在问题,然后继续查看实际数据。我会看一下像:https://github.com/felixge/faster-than-c

基本原则:

  • 收集数据
  • 分析
  • 发现问题
  • 修复它们
  • 重复

他对每一个都有提示。

答案 1 :(得分:1)

如果你不使用Lo-Dash,只想要一个工具合并两个对象,包括它们的数组,请使用deepmerge:https://github.com/nrf110/deepmerge

npm install deepmerge