在C#中遍历树的递归Lambda表达式
时间:2020-03-05 18:52:55 来源:igfitidea点击:
有人可以告诉我如何实现递归lambda表达式来遍历C#中的树结构。
解决方案
回答
假设一个神话般的对象TreeItem,它包含一个Children集合来表示层次结构。
public void HandleTreeItems(Action<TreeItem> item, TreeItem parent) { if (parent.Children.Count > 0) { foreach (TreeItem ti in parent.Children) { HandleTreeItems(item, ti); } } item(parent); }
现在调用它,通过将其名称打印到控制台来传入处理一个项目的lambda。
HandleTreeItems(item => { Console.WriteLine(item.Name); }, TreeItemRoot);
回答
一个正确的解决方案,实际上是许多功能编程语言中的惯用解决方案,将是使用定点组合器。简而言之:定点组合器回答了以下问题:如何将匿名函数定义为递归?但是解决方案并不简单,以致于撰写整篇文章来解释它们。
一个简单,实用的选择是在定义之前回到C:声明的滑稽动作。请尝试以下操作:
Func<int, int> fact = null; fact = x => (x == 0) ? 1 : x * fact(x - 1);
奇迹般有效。
回答
A simple alternative is to “go back in time” to the antics of C and C++: declaration before definition. Try the following: Func<int, int> fact = null; fact = x => (x == 0) ? 1 : x * fact(x - 1); Works like a charm.
是的,这确实有效,但有一点警告。 Chas可变参考。因此,请确保我们不会意外地执行以下操作:
Func<int, int> fact = null; fact = x => (x == 0) ? 1 : x * fact(x - 1); // Make a new reference to the factorial function Func<int, int> myFact = fact; // Use the new reference to calculate the factorial of 4 myFact(4); // returns 24 // Modify the old reference fact = x => x; // Again, use the new reference to calculate myFact(4); // returns 12
当然,此示例有些人为设计,但是在使用可变引用时可能会发生这种情况。如果我们使用aku的链接中的组合器,则将不可能。
回答
好的,我终于找到了一些空闲时间。
开始了:
class TreeNode { public string Value { get; set;} public List<TreeNode> Nodes { get; set;} public TreeNode() { Nodes = new List<TreeNode>(); } } Action<TreeNode> traverse = null; traverse = (n) => { Console.WriteLine(n.Value); n.Nodes.ForEach(traverse);}; var root = new TreeNode { Value = "Root" }; root.Nodes.Add(new TreeNode { Value = "ChildA"} ); root.Nodes[0].Nodes.Add(new TreeNode { Value = "ChildA1" }); root.Nodes[0].Nodes.Add(new TreeNode { Value = "ChildA2" }); root.Nodes.Add(new TreeNode { Value = "ChildB"} ); root.Nodes[1].Nodes.Add(new TreeNode { Value = "ChildB1" }); root.Nodes[1].Nodes.Add(new TreeNode { Value = "ChildB2" }); traverse(root);