3

頻繁に使用されるコード パスで 2 つのオブジェクトをマージする必要があります。コードは機能しますが、速度が十分に最適化されていないのではないかと懸念しており、思いついたものを改善/置き換えるための提案を探しています。私はもともと、この号の最後にある例に取り組み始めました: 2 つの JavaScript オブジェクトのプロパティを動的にマージするにはどうすればよいですか? . このソリューションは、単純なオブジェクトに適しています。ただし、私のニーズにはひねりがあり、パフォーマンスの問題が発生します。次のようなアレイをサポートできる必要があります。

  1. 単純な値の配列は、新しいオブジェクトで値を探し、それらを既存のオブジェクトの最後に追加し、
  2. オブジェクトの配列は、(id プロパティの存在に基づいて) オブジェクトをマージするか、既存の配列の最後に新しいオブジェクト (id プロパティが存在しないオブジェクト) をプッシュします。

関数/メソッドの複製は必要ありません。また、マージ後にオブジェクトが JSON 文字列に戻るため、hasOwnProperty についても気にしません。

これからパフォーマンスを最後まで引き出すのに役立つ提案があれば、大歓迎です。

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

2 に答える 2

3

私はチェックアウトします:https://github.com/bestiejs/lodash

_.merge「最適化された」関数のリストにはありませんが、これは戦闘でテストされ、強化されたものです。彼はパフォーマンス スイートも持っているので、パフォーマンス スイートにどのように貢献してmerge実装をある程度把握できるかを尋ねることができます。

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

編集:余談ですが、時期尚早に最適化することはありません。これが実際にユースケースの問題であるかどうかを確認してから、実際のデータに進みます。私は次のようなものを見ます: https://github.com/felixge/faster-than-c

基本的な信条:

  • データを収集します
  • 分析する
  • 問題を見つける
  • それらを修正する
  • 繰り返す

それぞれにコツがあります。

于 2012-10-08T15:07:02.863 に答える