【问题标题】:How do I sort a list and its children and their children using linq?如何使用 linq 对列表及其子项及其子项进行排序?
【发布时间】:2021-11-23 04:19:26
【问题描述】:

我有一个父子关系,例如:

public class MyType {

    public IList<MyType> Children {get;set;}
    public int Order {get;set;}

}

我想选择列表,以便每个级别都按顺序排列。

我可以轻松地为顶层做到这一点:

mylist.Children.OrderBy(x => x.Order)

但是我该如何为每组孩子做呢?

最终结果将是列表或类型及其所有子项,并且所有子项(等等)都按 Order 正确排序。

谢谢。

【问题讨论】:

    标签: c# linq


    【解决方案1】:

    您可以通过向MyType 添加一种方法来执行递归排序,如下所示:

    public class MyType
    {
        public IList<MyType> Childrens { get; set; }
        public int Order { get; set; }
    
        public void RecursiveOrder()
        {
            Childrens = Childrens.OrderBy(x => x.Order)
                .ToList();
    
            Childrens.ToList().ForEach(c => c.RecursiveOrder());
        }
    } 
    

    【讨论】:

      【解决方案2】:

      如果您使用 SortedList 作为您的基础子集合,您可以保持子排序。然后您可以公开Values 属性以获取值。添加到列表时,只需通过 order 键入项目即可。

      例如,

      public class MyType
      {
          public MyType(int order)
          {
              this.order = order;
          }
      
          private int order;
          private SortedList<int, MyType> children = new SortedList<int, MyType>();
      
          public int Order { get { return order; } }
          public IList<MyType> Children { get { return children.Values; } }
      
          public void AddChild(MyType child)
          {
              children.Add(child.order, child);
          }
      }
      

      否则,您可能希望对列表进行递归排序。在这里使用 LINQ 是不合适的。充其量,LINQ 将允许您按排序顺序遍历子级,但它实际上不会对基础列表进行排序,除非您将列表实例替换为排序版本。如果底层列表有一个Sort() 方法(通用List&lt;T&gt; 有),那么就使用它。

      private List<MyType> children;
      public void EnsureSorted()
      {
          children.Sort();
          foreach (var child in children)
              child.EnsureSorted();
      }
      

      不过,从排序列表开始会容易得多。

      【讨论】:

        【解决方案3】:

        我同意 Jeff 的观点,最简单的答案是存储已排序的数据(如果这将成为您的主要访问模式)。但是假设你真的想用 Linq 做到这一点:

        首先,如果你知道你只想要两个级别的排序,你可以这样做:

        myList.Children.OrderBy(x => x.Order)
            .Select(c => c.Children.OrderBy(x => x.Order))
        

        但是,如果您真正想要的是完全递归排序,一直向下怎么办?

        delegate IEnumerable<MyType> RecursiveFunc(MyType data, RecursiveFunc self);
        RecursiveFunc op = (data, func) => data.Children.OrderBy(x => x.Order)
            .Select(x => func(x, func));
        
        IEnumerable<MyType> result = op(myList, op);
        

        只是写让我的大脑受伤,我还没有尝试运行它,所以祝你好运!它归结为将 linq 表达式 (lambda) 传递给自身,以递归方式将自身应用到树中。

        【讨论】:

          【解决方案4】:

          试试这个

          mylist.Children.OrderBy(x => x.Order).ThenBy( x => x.order).ToList();
          

          【讨论】:

            【解决方案5】:

            如果最终结果只是必须是子列表(而不是具有嵌套子节点的父列表),您可以使用SelectMany

            IEnumerable<Child> result  = parents
                .SelectMany(p => p.Children)
                .OrderBy(child => child.Order);
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-01-01
              • 2023-03-05
              • 2013-10-17
              相关资源
              最近更新 更多