Linq SelectMany基于两个属性

时间:2018-09-28 16:10:09

标签: c# linq

我上了这个课:

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个节点(父节点的左右节点)。

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);

希望有帮助!