2015-10-14 41 views
1

我刚刚修改了this answer的代码,使其成为一个通用的树状构建器,然后我提出了一些作品,但是最终我引入了一个Tuple来使其工作。我很确定它可以写得更直接,但我看到它有困难..可以在不引入Tuple的情况下编写TreeBuilder函数吗?

我引入Tuple的根本原因是因为当时我迭代孩子,我还没有转换这些孩子们进入树节点了吗?我是用我的方法创建了这个问题,还是我用代码解决问题的内在原因?

这里的用法,然后树构建器:

// USAGE 
var document = DocumentModel.Load(@"Part CareAlerts Page 1 Part 1.docx", LoadOptions.DocxDefault); 
var tree = BuildTree<Element, Node>(
    document, 
    elt => elt.GetChildElements(false), 
    elt => new Node(elt.ElementType.ToString()) {Content = elt.Content.ToString().Trim()}, 
    (parent, child) => parent.Children.Add(child)); 

// TREE BUILDER FUNCTION 
public static TNode BuildTree<TIn, TNode>(TIn root, Func<TIn, IEnumerable<TIn>> childSelector, 
    Func<TIn, TNode> createNode, Action<TNode, TNode> connectNodes) 
    where TIn : class 
    where TNode : class 
{ 
    var stack = new Stack<Tuple<TNode, TIn>>(new[] {Tuple.Create(default(TNode), root)}); 
    TNode tree = null; 
    while (stack.Any()) 
    { 
     var next = stack.Pop(); 
     var result = createNode(next.Item2); 
     if (tree == null) 
     { 
      tree = result; 
     } 
     if (next.Item1 != null) 
     { 
      connectNodes(next.Item1, result); 
     } 
     foreach (var child in childSelector(next.Item2).Reverse()) 
     { 
      stack.Push(Tuple.Create(result, child)); 
     } 
    } 
    return tree; 
} 
+0

不使用一个元组?创建一个类来替换元组实例并使用它... –

+0

为什么不创建一个类或结构来保存这两个值? –

+0

凭借如此高的声誉得分,我会假设你知道这对SO来说不是一个好的合适问题。 – DavidG

回答

2

我觉得这样做的工作:

public static TNode BuildTree<TIn, TNode>(TIn root, Func<TIn, IEnumerable<TIn>> childSelector, 
    Func<TIn, TNode> createNode, Action<TNode, TNode> connectNodes) 
    where TIn : class 
    where TNode : class 
{ 
    var tree = createNode(root); 

    var children = 
     childSelector(root) 
      .Select(c => BuildTree(c, childSelector, createNode, connectNodes)) 
      .ToArray(); 

    children 
     .ForEach(child => connectNodes(tree, child)); 

    return tree; 
} 

我通过TIn去除约束和运行此代码测试这样的:

var tree = BuildTree<int, Tree<int>>(
    1, 
    elt => Enumerable.Range(2, 2).Select(n => elt * n).Where(x => x < 100), 
    elt => new Tree<int>() { Value = elt }, 
    (parent, child) => parent.Add(child)); 

public class Tree<T> : List<Tree<T>> 
{ 
    public T Value { get; set; } 
} 

或者更好的是这样的:

var tree = BuildTree<int, XElement>(
    1, 
    elt => Enumerable.Range(2, 3).Select(n => elt * n).Where(x => x < 16), 
    elt => new XElement("Node", new XAttribute("Value", elt)), 
    (parent, child) => parent.Add(child)); 

其中给出这样的:

<Node Value="1"> 
    <Node Value="2"> 
    <Node Value="4"> 
     <Node Value="8" /> 
     <Node Value="12" /> 
    </Node> 
    <Node Value="6"> 
     <Node Value="12" /> 
    </Node> 
    <Node Value="8" /> 
    </Node> 
    <Node Value="3"> 
    <Node Value="6"> 
     <Node Value="12" /> 
    </Node> 
    <Node Value="9" /> 
    <Node Value="12" /> 
    </Node> 
    <Node Value="4"> 
    <Node Value="8" /> 
    <Node Value="12" /> 
    </Node> 
</Node> 
相关问题