我是Javascript的新手,我有一些课程,但我还在学习它,我正在努力用JSON制作树。我在这里查看了其他答案,但我似乎无法理解减少,递归和jquery thingys。所以我创造了自己的功能。
但首先,我的JSON看起来像这样:
var data = [{
"id": 51,
"name": "root"
}, {
"id": 54,
"name": "app",
"parentId": 53
}, {
"id": 55,
"name": "text.txt",
"parentId": 54
}, {
"id": 53,
"name": "share",
"parentId": 52
}, {
"id": 52,
"name": "local",
"parentId": 51
}];
这些函数处理JSON对象:
var treeNode = function(nodeId, name) {
var children = [];
this.nodeId = nodeId;
this.name = name;
this.parentNode = null;
this.setParent = function(parentNode) {
this.parentNode = parentNode;
};
this.addChild = function(node){
children.push(node);
node.setParent(this);
};
};
var Tree = function() {
this.nodes = [];
this.findNodeById = function(nodeId) {
for (var i=0; i<this.nodes.length; i++) {
if (this.nodes[i].nodeId === nodeId) {
return this.nodes[i];
}
}
return null;
};
this.createNode = function(nodeId, name, parentNode) {
var node = new treeNode(nodeId, name);
if (parentNode) {
parentNode.addChild(node);
}
this.nodes.push(node);
}
};
function createTree(data) {
var tree = new Tree();
var temp = [];
for (var i=0; i<data.length; i++) {
var inputNode = data[i];
var parentNode = inputNode.parentId ? tree.findNodeById(inputNode.parentId) : null;
tree.createNode(inputNode.id, inputNode.name, parentNode);
}
return tree.nodes;
}
然后我调用函数:createTree(data);
所以在经过多次调试尝试制作功能之后,我终于意识到我可能在某个地方犯了一个错误,因为现在54和53节点的父母没有显示我只是无法绕过我的脑袋我做错了什么,我该如何解决?有人可以帮帮我吗?
非常感谢任何建议。
答案 0 :(得分:2)
您的代码一般看起来不错。问题是算法 它与插入节点的顺序直接相关。
你有一棵空树 首先,插入节点#51。现在,你有一个单节点#51的树 然后尝试插入节点#54,其中parentNode#53 ...不存在。
这里
var parentNode = inputNode.parentId ? tree.findNodeById(inputNode.parentId) : null;
你调用tree.findNodeById
,它遍历你的树,找不到节点53(它还没有在树中),并返回null
。
因此,您的第二个节点将parentNode
设置为null
,而不是节点#53。
基本思想是,您始终需要确保对于每个插入的节点,其父节点已经在树中。
我想到的最简单的输入数据解决方案是在插入前按升序对parentNode
上的数组进行排序。
它将保证您始终在父节点之后插入子节点,但它仅在节点以拓扑顺序编号时才有效。
这意味着parentId
始终小于id
。例如,节点5不能拥有ID为7的父级。
此处,它适用于您的输入数据:
var data = [{
"id": 51,
"name": "root"
}, {
"id": 54,
"name": "app",
"parentId": 53
}, {
"id": 55,
"name": "text.txt",
"parentId": 54
}, {
"id": 53,
"name": "share",
"parentId": 52
}, {
"id": 52,
"name": "local",
"parentId": 51
}];
var treeNode = function(nodeId, name) {
var children = [];
this.nodeId = nodeId;
this.name = name;
this.parentNode = null;
this.setParent = function(parentNode) {
this.parentNode = parentNode;
};
this.addChild = function(node){
children.push(node);
node.setParent(this);
};
};
var Tree = function() {
this.nodes = [];
this.findNodeById = function(nodeId) {
for (var i=0; i<this.nodes.length; i++) {
if (this.nodes[i].nodeId === nodeId) {
return this.nodes[i];
}
}
return null;
};
this.createNode = function(nodeId, name, parentNode) {
var node = new treeNode(nodeId, name);
if (parentNode) {
parentNode.addChild(node);
}
this.nodes.push(node);
}
};
function createTree(data) {
// HERE, you sort your array by parentId ASC:
data = data.sort(function(a, b) {
return a.parentId - b.parentId;
});
var tree = new Tree();
var temp = [];
for (var i=0; i<data.length; i++) {
var inputNode = data[i];
var parentNode = inputNode.parentId ? tree.findNodeById(inputNode.parentId) : null;
tree.createNode(inputNode.id, inputNode.name, parentNode);
}
return tree.nodes;
}
console.log(createTree(data));
但是,如果您的节点是随机编号的,那么您需要实施topological sorting而不是parentId
的简单排序。
顺便说一句,您可能希望使用对象映射而不是数组,以便不会每次都迭代它。它会提高O(n)
次 - O(1)
而不是O(n)
:
var Tree = function() {
this.nodes = {};
this.findNodeById = function(nodeId) {
return nodes[nodeId];
};
this.createNode = function(nodeId, name, parentNode) {
var node = new treeNode(nodeId, name);
if (parentNode) {
parentNode.addChild(node);
}
if (this.nodes[nodeId]) {
throw new Error("There is already node with ID " + nodeId + " in the tree.");
}
this.nodes[nodeId] = node;
}
};