2012-03-03 115 views
2

你能想出更好的辦法來重映射這個JavaScript對象:JavaScript對象 - 重映射屬性(由Key)

{ 
    "id": 123, 
    "child.id": 456, 
    "child.child.id": 789 
} 

...這個JavaScript對象:

{ 
    "id": 123, 
    "child": { 
     "id": 456, 
     "child": { 
      "id": 789 
     } 
    } 
} 

有必須是更短或更快的解決方案。這是我的嘗試:

var original = { 
    "id": 123, 
    "child.id": 456, 
    "child.child.id": 789 
}; 

var result = {}; 

Object.keys(original).forEach(function(key) { 
    var node = result; 
    var keys = key.match(/(\w+)/g); 

    for (var i = 0; i < keys.length; i++) { 
     if (!node[keys[i]]) { 
      node[keys[i]] = {}; 
     } 
     if (i == keys.length - 1) { 
      node[keys[i]] = original[key]; 
     } else { 
      node = node[keys[i]]; 
     } 
    } 
}); 

回答

3

我與你原始的方法去,但使用遞歸,似乎在我測試過的broswers以稍快的是(除了Safari和Opera和他們恰好等於,不知道這是爲什麼。):

function remapObject(original){ 
    var result = {}; 
    Object.keys(original).forEach(function(key) { 
     function splitNode(node, nodes){ 
      var name = nodes.shift() 
      node[name] = (nodes.length >= 1) 
       ? splitNode(node[name] || {}, nodes) 
       : original[key]; 
      return node; 
     } 
     splitNode(result, key.split(".")); 
    }); 
    return result; 
} 

var original = { 
     "id": 123, 
     "child.id": 456, 
     "child.other": 789 
    }, 
    result = remapObject(original) 

console.log(original); 
console.log(result); 

小提琴是在這裏:http://jsfiddle.net/hyperthalamus/3A9NQ/ jsperf測試是在這裏:http://jsperf.com/mapping-by-keys

編輯: 我不得不在花費大量時間處理閉包和優化等等之後,最近(再次)做一些與此類似的事情。下面是一個不依賴於Object.keys或array.forEach的版本。 array.forEach通常對性能不利,並且這兩種方法都是have limited browser support。下面的函數已經被優化以便重用,因爲這個函數在我的應用程序的初始化中使用了很多。我在這裏發佈(3個月後),因爲它非常適合我的需求,我想我會分享,儘管這可能是矯枉過正。

var remapObject = (function() { 
    "use strict"; 
    var nodeSplit = function (key, original) { 
     return function splitNode(node, nodes) { 
      var name = nodes.shift(); 
      node[name] = (nodes.length >= 1) ? splitNode(node[name] || {}, nodes) : original[key]; 
      return node; 
     }; 
    }; 
    return function (original) { 
     var result = {}, 
      prop, 
      splitNode; 
     for (prop in original) { 
      if (original.hasOwnProperty(prop)) { 
       nodeSplit(prop, original)(result, prop.split(".")); 
      } 
     } 
     return result; 
    }; 
}()); 

頂部的功能是初始化外殼內創建一次,並返回功能,以避免循環創建一個內部的功能,因爲這一般不贊成優化左右,有人告訴我。

如果關注的是文件的大小,一個壓縮版本是在這裏:

var remapObject=function(){var h=function(a,b){return function g(d,e){var f=e.shift();d[f]=1<=e.length?g(d[f]||{},e):b[a];return d}};return function(a){var b={},c;for(c in a)a.hasOwnProperty(c)&&h(c,a)(b,c.split("."));return b}}(); 
+0

幾乎有@Shane:不會一起工作:'變種原= { 「ID」:123, 「child.id」 :456,「child.other」:789};'例如。就像**遞歸**方法一樣! – 2012-03-03 17:40:28

+0

現在就試試,如果可以的話,我會修改我原來的答案 http://jsfiddle.net/hyperthalamus/3A9NQ/2/ – Shane 2012-03-03 17:50:06

+0

非常好,非常感謝! _(我也會更新這個問題。)_ – 2012-03-03 18:04:00