我正在挑战从所有html元素构建树。我完成了90%,但是我被卡住了......
如何将此字符串更改为树?:
mystring =“red1 /(none)-red2 / red1-blue1 / red2-blue2 / red2-blue3 / red2-red3 / red1-red4 / red3-red5 / red4-red6 / red5-blue4 / red6”; < / p>
按“ - ”拆分后,我们会:
10组 - &gt; (参数1)/(参数2)
第一个参数是对象, 第二个参数是'in-what-it-it-be-contained'
我不知道如何在'parameter2'中移动每个'parameter1'。 (注意:有时参数1将是参数1的参数2)
我对参数的意思的可视示例是在另一个参数内:(此示例完全使用上面的字符串)
可能我们应该使用数组?,idk ......我完全迷失了:sadface:
答案 0 :(得分:2)
我认为这更简洁直接。它使用对象作为字典来查找父对象,而不是必须递归迭代树以查找父对象的函数。递归函数很昂贵。对象查找很快。
首先,为方便起见,我定义了一个对象类型:
function TreeNode(name) {
this.Name = name;
this.Children = [];
}
然后我会添加一个方法来完成这项工作。这解析了你的树字符串:
TreeNode.ParseTree = function (treeString) {
var root = new TreeNode("");
var nodes = {};
var pairs = treeString.split("-");
pairs.forEach(function(pair) {
var parts = pair.split("/");
var parentName = parts[1];
var childName = parts[0];
var node;
if (parentName == "(none)") {
node = root;
root.Name = childName;
}
else {
node = new TreeNode(childName);
nodes[parentName].Children.push(node);
}
nodes[childName] = node;
});
return root;
};
就是这样!现在,为了获得树的可视化表示,您可以向TreeNode
添加一些原型方法。首先,覆盖.toString()
:
TreeNode.prototype.toString = function(indent) {
indent = indent || "";
var strings = [indent + this.Name];
this.Children.forEach(function(child) {
strings.push(child.toString(indent + " "));
});
return strings.join("\n");
};
然后,添加.Render()
方法以在网页中显示树:
TreeNode.prototype.Render = function(container) {
var nodeEl = container.appendChild(document.createElement("div"));
nodeEl.className = "treeNode";
var nameEl = nodeEl.appendChild(document.createElement("div"));
nameEl.className = "treeNodeName";
nameEl.appendChild(document.createTextNode(this.Name));
var childrenEl = nodeEl.appendChild(document.createElement("div"));
childrenEl.className = "treeNodeChildren";
this.Children.forEach(function(child) {
child.Render(childrenEl);
});
return nodeEl;
};
这里有效:http://jsfiddle.net/gilly3/wwFBx/
编辑:我没有注意到帖子中的jQuery标记,这里是一个渲染方法,它都是jQuery,并且生成更简单的HTML,你似乎暗示你想要的是:
TreeNode.prototype.Render = function(container) {
var el = $("<div>").appendTo(container).text(this.Name);
$.each(this.Children, function() {
this.Render(el);
});
return el;
};
这个JSFiddle使用jQuery,甚至用Array.forEach
取代$.each
:http://jsfiddle.net/wwFBx/1/
作为替代方案,您可以考虑将树序列化为JSON。例如:
"{\"Name\":\"red1\",\"Children\":[{\"Name\":\"red2\",\"Children\":[{\"Name\":\"blue1\",\"Children\":[]},{\"Name\":\"blue2\",\"Children\":[]},{\"Name\":\"blue3\",\"Children\":[]}]},{\"Name\":\"red3\",\"Children\":[{\"Name\":\"red4\",\"Children\":[{\"Name\":\"red5\",\"Children\":[{\"Name\":\"red6\",\"Children\":[{\"Name\":\"blue4\",\"Children\":[]}]}]}]}]}]}"
或者也许:
"{\"red1\":{\"red2\":{\"blue1\":{},\"blue2\":{},\"blue3\":{}},\"red4\":{\"red5\":{\"red6\":{\"blue4\":{}}}}}}"
通过JSON.parse()
解析字符串。
免责声明:我引用了现代浏览器内置的Array.forEach()
和JSON.parse()
,但旧浏览器不支持这些内容。要在旧版浏览器中启用这些功能,请参阅此documentation on Array.forEach()
和此shim for JSON.parse()
。
答案 1 :(得分:1)
这是我将如何做到这一点,使用一系列“未放置”元素并循环遍历它们直到它们全部放置:
var str = "red1/(none)-red2/red1-blue1/red2-blue2/red2-blue3/red2-red3/red1-red4/red3-red5/red4-red6/red5-blue4/red6";
var unplaced = [];
var tree = null;
var elements = str.split(/[\/\-]/);
function findNodeByName(nodeName, context) {
if(context.name === nodeName) return context;
for(var i = 0; i < context.children.length; i++) {
var subSearch = findNodeByName(nodeName, context.children[i]);
if(subSearch) return subSearch;
}
return null;
}
var element, node, parent, thisElement, i;
for(i = 0; node = elements[i]; i += 2) {
node = elements[i];
parent = elements[i + 1];
thisElement = {name: node, children: []};
if(!tree && parent === '(none)') {
tree = thisElement;
} else if(tree) {
var parentNode = findNodeByName(parent, tree);
if(parentNode) {
parentNode.children.push(thisElement);
} else {
unplaced.push(thisElement);
}
}
}
var oldLength;
while(unplaced.length) {
oldLength = unplaced.length;
for(i = 0; element = unplaced[i]; i++) {
var parentNode = findNodeByName(parent, tree);
if(parentNode) {
parentNode.children.push(element);
unplaced.splice(i, 1);
i--;
}
}
if(oldLength === unplaced.length) {
throw new SyntaxError("The string is not a valid tree.");
}
}
// The result is contained in "tree".
您可以在http://jsfiddle.net/minitech/tJSpN/
看到结果一个有功能:http://jsfiddle.net/minitech/tJSpN/1/
还有一个错误检查更多:http://jsfiddle.net/minitech/tJSpN/2/
答案 2 :(得分:1)
实际上,我发现使用JQuery函数AppendTo()
更简单/更短/更整洁的方式我们只需:
拆分参数......
为每个(参数1)创建一个 div
使用循环移动(parameter2)内的每个(parameter1) JQuery提供的非常棒的AppendTo()函数
最好的是它们实际上在它们内部,因此您可以轻松地设置隐藏/显示效果以产生很酷的效果
答案 3 :(得分:0)
您可以尝试创建以下形式的树节点:
node = {
str:"red1",
subBranches : new Array()
}
完成后,您可以添加遍历数组的子分支,为每个找到的正确对添加此类节点,并删除已放置在rootNode.subBranches
中的对。然后,您递归地为每个子分支执行相同的操作。