代码之家  ›  专栏  ›  技术社区  ›  Ashkan Mobayen Khiabani

基于两个属性的Linq SelectMany[duplicate]

  •  0
  • Ashkan Mobayen Khiabani  · 技术社区  · 6 年前

    我有一门课:

    public class Node
    {
        public string Name {get; set;}
        public Node Left {get; set;}
        public Node Right{get; set;}
    } 
    

    现在我有一个树,每个节点都有一个左节点和右节点,每个节点都有左节点和右节点,以此类推。

    我想得到 Name 在树中的所有节点中,我不能使用SelectMany。 我可以用几种方法来实现这一点,比如使用递归函数,但我真的很想知道如何使用Linq来实现这一点。

    tree.SelectMany(x=> new List<Node> {x.Left, x.Right}); 
    

    上面的代码只返回2个节点(父节点的左侧和右侧节点)。

    2 回复  |  直到 6 年前
        1
  •  1
  •   James P    6 年前

    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<节点> ,你可以做一个简单的 Select()

    foreach (var name in tree.ToEnumerable().Select(node => node.Name))
    {
        Console.WriteLine(name);
    }
    

    SelectMany 自从你的 节点 IEnumerable<节点> SelectMany 当我们需要把许多序列合并成一个序列的时候。

        2
  •  0
  •   Olivier Belanger    6 年前

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

    如果我说的对的话:打电话的时候 GetAllNodes()

    List<string> Names = YourList.Select(x => x.Name);
    

    希望有帮助!