【问题标题】:Recursively create all given tree paths in a list?递归地在列表中创建所有给定的树路径?
【发布时间】:2013-08-03 01:37:45
【问题描述】:

我有一些看起来像的字符串:

/Test Town
/Test Town/Interior
/Test Dungeon/Secret

给定一个任意路径列表,如何自动生成叶节点?我想解决方案涉及递归,但我不太明白。

我尝试使用循环来做到这一点,但我只得到了第一级。

上面会产生类似的东西:

【问题讨论】:

  • 您是否尝试过滤列表以仅返回叶节点?或者你想要一个树结构作为结果?
  • @Enigmativity 我只想要树结构 - 所以一个根节点,然后所有子节点都分开了。如果不清楚,我会用图片编辑我的帖子。

标签: c# winforms recursion treeview


【解决方案1】:

这很好用。

首先,我必须创建一个树结构:

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&lt;T&gt; 类,那么这只是三行代码。很简单。


作为替代方案,如果您不想使用匿名方法,您可以像这样修改树类:

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&lt;T&gt; 类。

第一个解决方案意味着您可以使用任何树结构。


这是适用于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()));

【讨论】:

  • 我想我必须按顺序遍历这棵树并从中创建树节点?
  • @VaughanHilts - 不,只需将我的 Tree&lt;T&gt; 课程替换为您正在使用的课程即可。您可能需要对代码进行一些调整,但您应该能够相当轻松地做到这一点。
  • StartWith 方法是在哪里定义的?
  • 现在就试一试吧。希望我能把它包在我的头上。 :)
  • @fcuesta - 抱歉,StartWith 是来自 Reactive Framework 团队的交互式扩展。我将用Concat 替换它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-23
  • 1970-01-01
  • 2015-06-01
  • 2021-09-19
  • 2012-09-13
  • 2018-04-04
相关资源
最近更新 更多