2012-01-31 9 views
2

私はツリーとして表示する必要がある、ディレクトリである文字列のソートされたリストを持っています。例えばJava:文字列をツリーに変換する

、私はこれらの文字列がある場合:私は現在、リストを経由して親」を追跡することを考えている

folder a 
|- folder b 
| |- file 1 
| |- file 2 
|- folder c 

"folder a/folder b/file 1" 
"folder a/folder b/file 2" 
"folder a/folder c" 

をとして、私はそれらを表示する必要があります最初の文字列の場合は "folder a/folder b"とし、 "親フォルダ"が同じかどうかに応じてツリーを構築します。これは親フォルダを通って戻っていくのがかなり複雑に思えますし、誰かがこれをやるのがより簡単で効率的な方法を勧めているのだろうかと思っていましたか?

文字列を繰り返し処理して実際にツリーを作成し、それを表示する前にツリー全体を反復するのに役立ちますか?すべてのデータが文字列として保存されている(このツリーは保存されません)ので、表示するたびにツリーデータ構造を構築する必要があります。

+2

文字列のリストをツリーデータ構造に変換しようとしているか、文字列のリストのツリー表現を出力しようとしていますか? – ggreiner

+0

@ggreiner私はそれをツリー表現として表示しようとしています。 – dee

答えて

4

のようなノードオブジェクトを作成することができます。ツリーを印刷したいだけなら、このスニペットをチェックすることができます。あなたが望むものを出力します。

import java.util.ArrayList; 
import java.util.Collections; 
import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 

public class StringTree { 

    public static void main(String[] args) { 

    List<String> folders = new ArrayList<String>(); 
    folders.add("folder a/folder b/file 1"); 
    folders.add("folder a/folder b/file 2"); 
    folders.add("folder a/folder c"); 
    // for a non-lexically sorted folder list 
    Collections.sort(folders); 

    Map<Integer, String> map = new HashMap<Integer, String>(); 
    for (String path : folders) { 
     String[] parsedPath = path.split("/"); 
     boolean newBranch = false; 
     for (int i = 0; i < parsedPath.length; i++) { 
     newBranch |= !parsedPath[i].equals(map.get(i)); 
     if (newBranch) { 
      map.put(i, parsedPath[i]); 
      print(i, parsedPath[i]); 
     } 
     } 
    } 
    } 

    private static void print(int level, String item) { 
    String tab = ""; 
    for (int i = 0; i < level; i++) 
     tab = tab + ((i == 0) ? "| " : "|- "); 
    System.out.println(tab + item); 
    } 

} 

更新:データとバグを修正

folders.add("folder a/folder b/file 1"); 
folders.add("folder b/folder b/file 1"); 
+0

ここに何か問題があります。このデータで確認してください: 'folders.add(" folder a/folder b/file 1 "); \t \t folders.add( "folder b/folder b/file 3"); \t \t folders.add( "folder a/folder b/file 2"); \t \t folders.add( "folder a/folder c"); \t \t folders.add( "folder b/folder c"); \t \t folders.add( "folder b/folder c"); \t \t folders.add( "folder b/folder b/file 2"); \t \t folders.add( "folder b/folder c"); \t \t folders.add( "folder b/folder d"); 'Sryはコメントの中でそれをどのようにフォーマットするのか分からない。 – msi

+1

あなたは 'folder b 'を持っていますが、それは望みますか?コードはソートされたフォルダのリストを想定しています...印刷する前にソートすることができます。私はその行を挿入します。 – mtsz

+0

ええ、私は並べ替え、私の間違いを忘れる。 – msi

0

基本的に、すべてが「ルート」から始まります。あなたは何ができるか は次のとおりです。

while(!End of List) 
{ 
    tempNode = Root; 
    1. Resolve each line into tokens (with '/' as delimiter) 
    2. while(hasMoreTokens()) 
     { 
      3. Check if nextToken() is the child of tempNode 
      4. If not, create node with nextToken(), continue till all tokens of line are exhausted. 
      5. If yes, go to tempNode.nextToken(). Go to step 3. 
     } 
} 

ツリーにあなたがリストの各ラインを通過するたびに作成しますこの方法です。

-1

ツリーを最初に作成してから表示してください。これは後で変更に対応できるためです。

class Node{ 
    // level deep of this node, can use to format the display like 
    // 4 level deep will have four leading spaces 
    private int level; 
    // the actual text 
    private String text; 
    // Parent Node for this, can be null if this is the root node, set this when creating 
    private Node parent; 
    // children of this Node 
    private List<Node> children; 
    // Getters and setters for the above properties.... 
} 
+0

Downvote。アルテアストは、OPの質問を見ましたか? –

+0

@SatadruBiswas: - この部分は、「文字列を繰り返し、最初にツリーを作成し、それを表示する前にツリーを繰り返すのに役立ちますか?私の答えが最初に与えられ、本当の懸念があります。誰かがこれをやるより簡単で効率的なやり方を推薦できるかどうか疑問に思っていましたか?コードサンプルはそのためのものです。あなたはOPの質問の質問を見つけることができますか? –

+0

'ツリーを最初に構築してから表示してください。これは後で変更に対応できるためです。 'のようなNodeオブジェクトを作成することができます。これはアルゴリズム全体が想定していることです。ツリーを最初に構築します。つまり、 'List 'をノードを含む 'Tree'に変換します。ノードがどのようにヘルプのように見えるべきかの説明をどのように与えるのでしょうか? –

6

お役に立てば幸いです。カタログの全体構造を構築します。短い名前とジェネリック医薬品の不足のために泣いてください。より読みやすくなることを願っています。

public static void main(String[] args) { 
    ArrayList<String> listOfPaths = new ArrayList<String>(); 
    listOfPaths.add("folder a/folder b/file 1"); 
    listOfPaths.add("folder a/folder b/file 2"); 
    listOfPaths.add("folder a/folder c"); 

    TreeMap structure = new TreeMap(); 
    for (String path : listOfPaths) { 
     String[] tmp = path.split("/", 2); // [ "folder a/", "folder b/file 1"] for first loops step 
     put(structure, tmp[0], tmp[1]); 
    } 

    print(structure, ""); 
} 
private static void put(TreeMap structure, String root, String rest) { 
    String[] tmp = rest.split("/", 2); 

    TreeMap rootDir = (TreeMap) structure.get(root); 

    if (rootDir == null) { 
     rootDir = new TreeMap(); 
     structure.put(root, rootDir); 
    } 
    if (tmp.length == 1) { // path end 
     rootDir.put(tmp[0], null); 
    } else { 
     put(rootDir, tmp[0], tmp[1]); 
    } 
} 
private static void print(TreeMap map, String delimeter) { 
    if (map == null || map.isEmpty()) 
     return; 
    for (Object m : map.entrySet()) { 
     System.out.println(delimeter + "-" + ((Map.Entry)m).getKey()); 
     print((TreeMap)((Map.Entry)m).getValue(), " |" + delimeter); 
    } 
} 
+0

+1がテストされ、動作します。 – mtsz

+1

ありがとう!これも動作しますが、@ mtszはあなたより少し早く回答しました。私は彼の答えを受け入れてあなたの+1を返しました – dee

+0

検索機能は既にThreeMapクラスに実装されていますか? – Boubakr

1

最終目標が何であるかによって大きく異なると思います。データを印刷するだけの場合、またはデータを処理する必要がある場合、またはアルゴリズムを操作する必要がある場合。

私の直感は、すべてLinkedHashMapを使って行い、基本的に地図の地図などにしています.2つの異なる可能な値があるので、これをきちんとやることはできますあなたのマップのためのフォルダとファイル。 LinkedHashMapを使用すると、データを挿入するときにデータの順序を維持することに注意してください。並べ替え、またはランダムな順序が必要な場合は、他の実装を選択できます。

基本的に、私は木(あなたにも再帰的にこれを行うことができます)を構築次に

public interface DirectoryEntry{ 
    boolean isFile; 
    boolean isFolder; 
} 

public class Folder implements DirectoryEntry{ 
    public boolean isFile(){ return false;} 
    public boolean isFolder(){ return true;} 

    private Map<String, DirectoryEntry> entries = new LinkedHashMap<String, DriectoyrEntry>(); 

    public Map<String, DirectoryEntry>getEntries(){ return entries;} 
    public void addFile(String filename){ entries.put(filename, new File();} 
    public void addFolder(String foldername){entries.put(foldername, new Folder();} 
} 

public class File implements DirectoryEntry{ 
    public boolean isFile(){ return true;} 
    public boolean isFolder(){ return false;} 
} 

次(擬似コード)のようなものとして、それを参照してくださいになります。そして、あなたを

Map<String, DirectoryEntry> entries = new LinkedHashMap<String, DirectoryEntry>() 

while(!end of list){ 
    Map entry = entries; 

    1. Split string on '/' 
    2. foreach(token){ 
     if file 
     entries.put(token, new File()); 
     else{ 
     if(!entry.containsKey(token)) 
      entry.put(token, new Folder); 

     // use the folder map for any sub-folders/files 
     entry = ((Folder)entry.get(token)).getEntries(); 
     } 
    } 
} 

をあなたの最終的なリストをスキャンし、好きなようにそれを再生することができます。 File and Folderを意図的に作成しましたが、必要に応じて追加のメタデータ/情報を追加できます。

これは、ファイル/フォルダを解析/マッピングする方法についてのアイデアを提供するための単なる選択肢に過ぎませんが、そのまま機能的な解決策を意味するものではありません。

私が言ったように、まず解析して印刷する方が簡単なのかどうかは、最終的なデータセットで達成したいことに依存します。しかし、私の腸の本能は、それをすべて解析し、あなたが見せているものがあなたが理解しているものであり、操作することを保証するためにあなたが解析したものを表示することでしょう。

-1

私はこのような単純なコードでそれを行うことができますツリーの実装を持っている:

PathTreeBuilder.Funnel<String, String> urlFunnel = new PathTreeBuilder.Funnel<String, String>() { 
    @Override 
    public List<String> getPath(String value) { 
     return Lists.newArrayList(value.split("/")); 
    } 
}; 
PathTreeBuilder<String, String> builder = new PathTreeBuilder<String, String>(urlFunnel); 
List<Tree<String>> build = builder.build(urls); 
build.toStringTree(); 

は、それが誰かの役に立つことを願っています。

関連する問題