拼合的IEnumerable有多个根节点,并选择Id属性 [英] Flatten IEnumerable with multiple root nodes and select Id property

查看:160
本文介绍了拼合的IEnumerable有多个根节点,并选择Id属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下的层次,我需要拼合这一点,选择所有编号秒。我已经尝试使用的SelectMany()这样的 .SelectMany(结点=> node.Children)。选择(结点=> node.Id) 。这将导致 3,5,6 列表。是否有可能,使用LINQ来获取完整列表的 1,2,3,4,5,6,7

I have the following hierarchy and I need to flatten this and select all Ids. I have tried using SelectMany() like this .SelectMany(node => node.Children).Select(node => node.Id). This will result in a list of 3,5,6. Is it possible, using Linq to get the complete list 1,2,3,4,5,6,7?


  • 节点(ID = 1)

  • 节点(ID = 2)

    • 节点(ID = 3)


    • 节点(n = 5)

    • 节点(ID = 6)

      • 节点(ID = 7)

      推荐答案

      您可以使用下面的扩展方法压扁层次(请参阅下面的答案更新替代扁平化算法):

      You can use following extension method for flattening hierarchy (see alternative flattening algorithm in answer update below):

      public static IEnumerable<T> Flatten<T>(
          this IEnumerable<T> source, Func<T, IEnumerable<T>> childrenSelector)
      {
          foreach (var item in source)
          {
              yield return item;
      
              var children = childrenSelector(item);
              if (children == null)
                  continue;
      
              foreach (var child in children.Flatten(childrenSelector))
                  yield return child;                
          }
      }    
      



      我需要孩子选择和递归得到孩子。然后投射很简单:

      I takes child selector and recursively yields children. Then projection is simple:

      var result = nodes.Flatten(n => n.Children).Select(n => n.Id);
      



      假定你有以下Node类:

      Assume you have following Node class:

      public class Node
      {    
          public Node(int id, params Node[] children)
          {
              Id = id;
              if (children.Any())
                  Children = new List<Node>(children);
          }
      
          public int Id { get; set; }
          public List<Node> Children { get; set; }
      }
      



      然后与样品等级:

      Then with your sample hierarchy:

      List<Node> nodes = new List<Node> {
          new Node(1),
          new Node(2, new Node(3)),
          new Node(4, new Node(5),
                      new Node(6, new Node(7)))
      };
      

      输出将是:

      1, 2, 3, 4, 5, 6, 7
      

      < STRONG>更新:您可以拼合层次不递归的使用情况(更好的性能):

      UPDATE: You can flatten hierarchy without usage of recursion (for better performance):

      public static IEnumerable<T> Flatten<T>(
          this IEnumerable<T> source, Func<T, IEnumerable<T>> childrenSelector)
      {
          Queue<T> queue = new Queue<T>();
          foreach (var item in source)
              queue.Enqueue(item);
      
          while (queue.Any())
          {
              T item = queue.Dequeue();
              yield return item;
              var children = childrenSelector(item);
              if (children == null)
                  continue;
      
              foreach (var child in children)
                 queue.Enqueue(child);
          }
      }
      

      这篇关于拼合的IEnumerable有多个根节点,并选择Id属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆