这个TreeBuilder函数可以在不引入元组的情况下编写吗?
本文关键字:情况下 元组 函数 TreeBuilder 这个 | 更新日期: 2023-09-27 18:17:49
我只是从这个答案中改编了代码,使其成为一个通用的树生成器,并且我所提出的工作,然而,我最终引入了Tuple来使其工作。我很确定它可以写得更直接,但我有麻烦看到它…
我引入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;
}
我想这样就可以了:
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>