從字符串路徑列表構造樹結構

[英]Construct a tree structure from list of string paths


I have a collection of string paths like ["x1/x2/x3","x1/x2/x4","x1/x5"] in a list. I need to construct a tree-like structure from this list which can be iterated to get a pretty printed tree. like this

我在列表中有一組字符串路徑,如[“x1 / x2 / x3”,“x1 / x2 / x4”,“x1 / x5”]。我需要從這個列表中構造一個樹狀結構,可以迭代得到一個漂亮的打印樹。像這樣

     x1
    /  \
   x5   x2
       /  \
      x3  x4

Any ideas/suggestions? I believe that the problem can be attacked first by processing the list of strings EDIT: The correct answer chosen was an elegant implementation, other suggestions were good too.

有什么想法/建議嗎?我相信通過處理字符串列表可以首先攻擊問題EDIT:選擇的正確答案是優雅的實現,其他建議也很好。

5 个解决方案

#1


Follow an implementation of naive implementation of a visitable tree:

遵循可訪問樹的天真實現的實現:

class Tree<T> implements Visitable<T> {

    // NB: LinkedHashSet preserves insertion order
    private final Set<Tree> children = new LinkedHashSet<Tree>();
    private final T data;

    Tree(T data) {
        this.data = data;
    }

    void accept(Visitor<T> visitor) {
        visitor.visitData(this, data);

        for (Tree child : children) {
            Visitor<T> childVisitor = visitor.visitTree(child);
            child.accept(childVisitor);
        }
    }

    Tree child(T data) {
        for (Tree child: children ) {
            if (child.data.equals(data)) {
                return child;
            }
        }

        return child(new Tree(data));
    }

    Tree child(Tree<T> child) {
        children.add(child);
        return child;
    }
}

interfaces for Visitor Pattern:

訪客模式的界面:

interface Visitor<T> {

    Visitor<T> visitTree(Tree<T> tree);

    void visitData(Tree<T> parent, T data);
}

interface Visitable<T> {

    void accept(Visitor<T> visitor);
}

sample implementation for Visitor Pattern:

訪客模式的示例實現:

class PrintIndentedVisitor implements Visitor<String> {

    private final int indent;

    PrintIndentedVisitor(int indent) {
        this.indent = indent;
    }

    Visitor<String> visitTree(Tree<String> tree) {
        return new IndentVisitor(indent + 2);
    }

    void visitData(Tree<String> parent, String data) {
        for (int i = 0; i < indent; i++) { // TODO: naive implementation
            System.out.print(" ");
        }

        System.out.println(data);
    }
}

and finally (!!!) a simple test case:

最后(!!!)一個簡單的測試用例:

    Tree<String> forest = new Tree<String>("forest");
    Tree<String> current = forest;

    for (String tree : Arrays.asList("x1/x2/x3", "x1/x2/x4", "x1/x5")) {
        Tree<String> root = current;

        for (String data : tree.split("/")) {
            current = current.child(data);
        }

        current = root;
    }

    forest.accept(new PrintIndentedVisitor(0));

output:

forest
  x1
    x2
      x3
      x4
    x5

#2


Just split each path by its delimiter and then add them to a tree structure one by one.
i.e. if 'x1' does not exist create this node, if it does exist go to it and check if there is a child 'x2' and so on...

只需通過分隔符拆分每個路徑,然后逐個將它們添加到樹結構中。即如果'x1'不存在則創建此節點,如果確實存在則轉到該節點並檢查是否存在子節點'x2'等等...

#3


I'd make the tree one string at a time.

我一次把樹打成一根繩子。

Make an empty tree (which has a root node - I assume there could be a path like "x7/x8/x9").

制作一個空樹(有一個根節點 - 我假設可能有一個像“x7 / x8 / x9”這樣的路徑)。

Take the first string, add x1 to the root node, then x2 to x1, then x3 to x2.

取第一個字符串,將x1添加到根節點,然后將x2添加到x1,然后將x3添加到x2。

Take the second string, see that x1 and x2 are already there, add x4 to x2.

取第二個字符串,看到x1和x2已經存在,將x4添加到x2。

Do this for every path you have.

為你擁有的每條路徑都這樣做。

#4


Create an Object Node which contains a parent (Node) and a List of children (Node).

創建一個對象節點,其中包含父節點(Node)和子節點列表(Node)。

First split the string using ",". For every splitted string you split the string using "/". Search for the first node identifier (e.g x1) in the root list. If you can find it, use the node to find the next node identifier (e.g. x2).

首先使用“,”拆分字符串。對於每個拆分的字符串,您使用“/”拆分字符串。在根列表中搜索第一個節點標識符(例如x1)。如果可以找到它,請使用該節點查找下一個節點標識符(例如x2)。

If you can not find a node, add the node to the last node you was able to find in the existing lists.

如果找不到節點,請將節點添加到您能夠在現有列表中找到的最后一個節點。

After you have created the list structure, you can print the list to the screen. I would make it recursive.

創建列表結構后,可以將列表打印到屏幕上。我會讓它遞歸。

NOT TESTED, just an animation

沒有測試,只是一個動畫

public void print(List nodes, int deep) {
    if (nodes == null || nodes.isEmpty()) {
        return;
    }

    StringBuffer buffer = new StringBuffer();
    for (int i = 0; i < deep; i++) {
        buffer.append("---");
    }

    for (Iterator iterator = nodes.iterator(); iterator.hasNext();) {
        Node node = (Node)iterator.next();

        System.out.println(buffer.toString() + " " + node.getIdentifier());

        print(node.getChildren(), deep + 1);
    }
}

#5


Make your tree for every string in array. Just split path for '/' , check whether the node exists in your tree or not, if it exists then move on... otherwise create a new node and add this node in childrens of parent node.

為數組中的每個字符串創建樹。只需拆分“/”路徑,檢查樹中是否存在節點,如果存在,則繼續...否則創建一個新節點並在父節點的子節點中添加該節點。

Iterate using recursion.

迭代使用遞歸。

Following is model for tree's node.

以下是樹節點的模型。

Class Node{
    string name;
    List<Node> childrens;

    Node(string name){
        this.name = name;
        this.childrens = new List<Node>();
    }
}

注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2009/06/17/afa88d68bff0a2bfcf623e064f01b402.html



 
  © 2014-2022 ITdaan.com 联系我们: