2012-03-03 114 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