任何人都可以帮助转换以下父子对象列表:
[ { “ name”:“ root”, “ _id”:“ root_id”, }, { “ name”:“ a1”, “ parentAreaRef”:{ “ id”:“ root_id”, }, “ _id”:“ a1_id”, }, { “ name”:“ a2”, “ parentAreaRef”:{ “ id”:“ a1_id”, }, “ _id”:“ a2_id”, }, { “ name”:“ a3”, “ parentAreaRef”:{ “ id”:“ a2_id”, }, “ _id”:“ a3_id”, }, { “name”:“ b1”, “ parentAreaRef”:{ “ id”:“ root_id”, }, “ _id”:“ b1_id”, }, { “ name”:“ b2”, “ parentAreaRef”:{ “ id”:“ b1_id”, }, “ _id”:“ b2_id”, }, { “name”:“ b3”, “ parentAreaRef”:{ “ id”:“ b1_id”, }, “ _id”:“ b3_id”, } ]
变成显示父子关系的树结构:
[ { “ name”:“ root”, “ _id”:“ root_id”, “children”:[ { “ name”:“ a1”, “ _id”:“ a1_id”, “children”:[ { “ name”:“ a2”, “ _id”:“ a2_id”, “children”:[ { “name”:“ a3” “ _id”:“ a3_id” } ] } ] }, { “ name”:“ b1”, “ _id”:“ b1_id”, “children”:[ { “name”:“ b2” “ _id”:“ b2_id” }, { “name”:“ b3” “ _id”:“ b3_id” } ] } ] } ]
(输出结构是一个允许有多个根的数组,但是如果我们能得到一个处理单个根的解决方案,那也很好。)
输出树如下所示:
根 | -a1 | | | - a2 | | | -a3 | -b1 | -b2 -b3
谢谢!
我有一个可行的解决方案。就解决问题,我可以给您一些提示。好消息是您的数据不包含对节点的任何前向引用。因此,您只需一次遍历数组就可以创建树。如果需要注意的话,您首先需要遍历整个数组以建立ID到节点的映射。
您的算法将如下所示。
children
这应该可以帮助您解决问题。如果您对此算法有特定的问题,我可以指出问题出在哪里以及如何解决,也可以发布解决方案并解释如何解决。
更新
我查看了您拥有的解决方案。实际上,您实际上不需要递归,可以使用我上面描述的算法来迭代地执行此操作。您还需要就地修改结构,这会使算法更加复杂。但是您在正确的道路上。这是我解决的方法:
var idToNodeMap = {}; //Keeps track of nodes using id as key, for fast lookup var root = null; //Initially set our loop to null //loop over data data.forEach(function(datum) { //each node will have children, so let's give it a "children" poperty datum.children = []; //add an entry for this node to the map so that any future children can //lookup the parent idToNodeMap[datum._id] = datum; //Does this node have a parent? if(typeof datum.parentAreaRef === "undefined") { //Doesn't look like it, so this node is the root of the tree root = datum; } else { //This node has a parent, so let's look it up using the id parentNode = idToNodeMap[datum.parentAreaRef.id]; //We don't need this property, so let's delete it. delete datum.parentAreaRef; //Let's add the current node as a child of the parent node. parentNode.children.push(datum); } });
现在root指向整个树。
root
小提琴。
对于元素数组为任意顺序的情况,则必须idToNodeMap首先进行初始化。该算法的其余部分大致相同(除了在地图上存储节点的行;这不是必需的,因为您已经在第一遍中完成了该行):
idToNodeMap
var idToNodeMap = data.reduce(function(map, node) { map[node._id] = node; return map; }, {});