2015-10-14 24 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> 
相關問題