2013-07-07 209 views
2

对不起,令人困惑的标题......我不知道更好的总结。我有一个对象数组。其中一些对象具有对其父对象的引用。类似的东西:从对象数组创建一个对象引用父对象

data: 
[ 
    {id: 2, parent: 1}, 
    {id: 1}, 
    {id: 3, parent: 1}, 
    {id: 5, parent: 3}, 
    {id: 4, parent: 3}, 
    {id: 6, parent: 2} 

] 

我想要做的是创建一个对象出这个数组,其中的子对象嵌套在他们的父母。像这样:

data: { 
    id: 1, 
    children: [ 
    { 
     id:2, 
     children: [ 
     {id: 6} 
     ] 
    }, 
    { 
     id:3, 
     children: [ 
     {id: 4}, 
     {id: 5} 
     ] 
    } 
    ] 
} 

有没有人知道这样做的聪明方式? 我知道我必须通过这个数组的每个对象来检查是否有父。但我怎样才能真正创造这个对象?

回答

2

不确定这是做到这一点的最佳方式,但至少它是一种方法。

  1. 首先遍历所有的节点:
    • 被放在一个查找表中的节点的idnodes)。
    • 找到root节点(没有parent的单节点)。
  2. 二回路(与查找表完成):
    • 检查是否nodeparent(存在于除root每个节点)。
    • 通过在查找表中查找id获取parent节点。
    • 获取parent.children数组,或创建它,如果它还不存在。
    • 将此node添加到该阵列。
    • 删除此nodeparent财产。

注意这改变了你的data对象的原始节点对象。这是有意的,因为树是通过存储对父节点中其他节点的引用来构建的。如果您需要保留原始节点data不变,则应在构建查找表时克隆节点对象。例如,您可以在查找forEach循环(使用jQuery时)中添加node = $.extend({}, node);作为第一行。

下面是一个实现和demonstration

var data = [ 
    {id: 2, parent: 1}, 
    {id: 1}, 
    {id: 3, parent: 1}, 
    {id: 5, parent: 3}, 
    {id: 4, parent: 3}, 
    {id: 6, parent: 2} 
]; 

// Node lookup table 
var nodes = {}; 
// Root node 
var root = null; 
// Fill lookup table and find root 
data.forEach(function(node) { 
    nodes[node.id] = node; 
    // Assuming only one root node 
    if(!("parent" in node)) { 
     root = node; 
    } 
}); 
// Build tree 
for(var id in nodes) { 
    var node = nodes[id]; 
    if("parent" in node) { 
     // Add to children of parent 
     var parent = nodes[node.parent]; 
     (parent.children = parent.children || []).push(node); 
     // Remove parent property (optional) 
     delete node.parent; 
    } 
} 
console.log(JSON.stringify(root));