如何把它变成一棵树?

时间:2011-08-25 18:20:07

标签: javascript jquery html

我正在挑战从所有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)

我对参数的意思的可视示例是在另一个参数内:(此示例完全使用上面的字符串)

http://img853.imageshack.us/img853/6893/grg.jpg

可能我们应该使用数组?,idk ......我完全迷失了:sadface:

4 个答案:

答案 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取代$.eachhttp://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. 拆分参数......

  2. 为每个(参数1)创建一个 div

  3. 使用循环移动(parameter2)内的每个(parameter1) JQuery提供的非常棒的AppendTo()函数

  4. 最好的是它们实际上在它们内部,因此您可以轻松地设置隐藏/显示效果以产生很酷的效果

答案 3 :(得分:0)

您可以尝试创建以下形式的树节点:

node = {
str:"red1",
subBranches : new Array()
}

完成后,您可以添加遍历数组的子分支,为每个找到的正确对添加此类节点,并删除已放置在rootNode.subBranches中的对。然后,您递归地为每个子分支执行相同的操作。