我有一些字符串看起來:以遞歸方式在列表中創建所有給定的樹路徑?
/Test Town
/Test Town/Interior
/Test Dungeon/Secret
鑑於pathes的任意列表,我怎麼能自動生成葉節點?我想象的解決方案涉及遞歸,但我不能完全明白。
我試圖用循環做,但我只有第一級。
以上會產生這樣的:
我有一些字符串看起來:以遞歸方式在列表中創建所有給定的樹路徑?
/Test Town
/Test Town/Interior
/Test Dungeon/Secret
鑑於pathes的任意列表,我怎麼能自動生成葉節點?我想象的解決方案涉及遞歸,但我不能完全明白。
我試圖用循環做,但我只有第一級。
以上會產生這樣的:
這工作得相當好。
首先,我不得不創建一個樹形結構:
public class Tree<T> : List<Tree<T>>
{
public Tree(T value, IEnumerable<Tree<T>> children)
{
this.Value = value;
this.AddRange(children);
}
public T Value { get; set; }
}
現在我需要一個遞歸函數來構建樹起來:
Func<
IEnumerable<IEnumerable<string>>,
IEnumerable<Tree<string>>>
buildTree = null;
buildTree = xss =>
xss
.ToLookup(xs => xs.FirstOrDefault(), xs => xs.Skip(1))
.Where(xs => xs.Key != null)
.Select(xs => new Tree<string>(xs.Key, buildTree(xs)));
然後,給我有一個字符串列表中一個lines
變量,我只需要執行:
var tree =
buildTree(lines
.Select(x => new [] { "Root", }.Concat(x.Split('/').Skip(1))));
就是這樣。如果您不指望Tree<T>
類,那麼這只是三行代碼。簡單。
作爲選擇,如果你不想使用匿名方法,你可以修改樹類,像這樣:
public class Tree<T> : List<Tree<T>>
{
public Tree(T value, IEnumerable<IEnumerable<T>> inner)
{
this.Value = value;
this.AddRange(inner
.ToLookup(xs => xs.FirstOrDefault(), xs => xs.Skip(1))
.Where(xs => xs.Key != null)
.Select(xs => new Tree<T>(xs.Key, xs)));
}
public T Value { get; set; }
}
現在,它會被稱爲是這樣的:
var tree = new Tree<string>("Root", lines.Select(x => x.Split('/').Skip(1)));
但是,這意味着您需要控制Tree<T>
類。
第一個解決方案意味着您可以使用任何樹結構。
下面是爲System.Windows.Forms.TreeNode
工作的版本:
Func<
IEnumerable<IEnumerable<string>>,
IEnumerable<TreeNode>>
buildTreeNode = null;
buildTreeNode = xss =>
xss
.ToLookup(xs => xs.FirstOrDefault(), xs => xs.Skip(1))
.Where(xs => xs.Key != null)
.Select(xs => new TreeNode(xs.Key, buildTreeNode(xs).ToArray()));
我想我會不得不對這棵樹進行按順序遍歷並且創建Tree-Nodes? –
@VaughanHilts - 不,只需將我的「樹
StartWith方法在哪裏定義? – fcuesta
你們是不是要過濾列表僅返回葉節點?或者你想要一個樹結構? – Enigmativity
@Enigmativity我只是想要樹結構 - 所以一個根節點,然後所有的孩子分開。如果不清楚,我會用照片編輯我的帖子。 –