我上了这个课:
data ex;
input x;
cards;
1
1
4
4
1
3
3
4
4
4
1
;
run;
现在我有了树,每个节点都有一个左右节点,每个节点都有左右节点,依此类推。
我想获取树中所有节点的public class Node
{
public string Name {get; set;}
public Node Left {get; set;}
public Node Right{get; set;}
}
,而SelectMany无法做到。
我可以通过几种方式来做到这一点,例如使用递归函数,但我真的很想知道如何使用Linq来完成它。
Name
上面的代码仅返回2个节点(父节点的左右节点)。
答案 0 :(得分:1)
LINQ中的所有内容都基于接口IEnumerable。因此,要使LINQ正常工作,必须将根Node
树转换为IEnumerable<Node>
。我们可以使用扩展方法来做到这一点。
public static class NodeHelper
{
public static IEnumerable<Node> ToEnumerable(this Node node)
{
var stack = new Stack<Node>();
if (node != null) stack.Push(node);
while (stack.Count > 0)
{
var current = stack.Pop();
yield return current;
if (current.Left != null) stack.Push(current.Left);
if (current.Right != null) stack.Push(current.Right);
}
}
}
有了IEnumerable<Node>
后,您就可以做一个简单的Select()
foreach (var name in tree.ToEnumerable().Select(node => node.Name))
{
Console.WriteLine(name);
}
您不需要使用SelectMany,因为您的Node
没有IEnumerable<Node>
的子节点,只有左节点和右节点。当我们需要将多个序列合并为一个序列时,使用SelectMany
。
希望这会有所帮助。
答案 1 :(得分:0)
这是我发现的东西:
class Node
{
public Node() {Children = new List<Node>();}
public IEnumerable<Node> GetSubTree()
{
return Children.SelectMany(c => c.GetSubTree()).Concat(new[] {this});
}
public List<Node> Children {get;set;}
}
class Tree
{
public Tree() {Roots = new List<Node>();}
public IEnumerable<Node> GetAllNodes()
{
return Roots.SelectMany(root => root.GetSubTree());
}
List<Node> Roots {get;set;}
}
如果我是对的:从Tree类调用GetAllNodes()
时,它将从树中的每个根获取所有节点。然后,如果您显然拥有一个名为Name的属性,则可以使用此名称:
List<string> Names = YourList.Select(x => x.Name);
希望有帮助!