【问题标题】:Order list by parent and child items按父项和子项排序的列表
【发布时间】:2014-02-27 15:04:35
【问题描述】:

我有一个必须由父母订购的产品列表,然后是该父母的所有孩子,然后是下一个父母,等等。

Product One
    Child One
    Child Two
Product Two
    Child One

这些产品都在一个带有父 id 字段的表中,子产品有一个父 id,但父项可以有一个空父项(表示该产品是顶级产品)

我在想类似以下的事情:

var list = GetProductList();
var newList = new List<ProductDTO>();

var parents = from p in list
    where p.Parent == null
    select p.Id;


foreach (var parent in parents)
{
    var tempList = new List<ProductDTO>();
    tempList.Add(list.FirstOrDefault(x => x.Id == parent));
    tempList.AddRange(list.Where(x => x.Parent == parent).OrderBy(x => x.Id));
    newList.AddRange(tempList);
}

有什么建议可以让我更干净一点吗?

【问题讨论】:

    标签: c# .net linq


    【解决方案1】:

    您可以尝试类似的方法。假设 parent 可以为空:

    var sorted = list.OrderBy(x => x.parent ?? x.id).ThenBy(x=>x.id);
    

    如果是字符串:

                var sorted = list.OrderBy(x =>
                {
                    if (x.parent == "null")
                        return x.id;
                    else
                        return Convert.ToInt32(x.parent);
                }).ThenBy(x => x.id);
    

    【讨论】:

    • 如果这个答案早一个小时,它会比我认为接受的答案更受欢迎
    【解决方案2】:

    鉴于“Parent”是可为空的属性(假设此处为可为空的 int)。以下应该为您提供与父子相关的有序列表:

     public class ProductDTO
     {
         public int Id { get; set; }
         public string Name { get; set; }
         public int? Parent { get; set; }
     }
    
     var products = new List<ProductDTO>();
     products.Add(new ProductDTO() { Id = 1, Name = "Product One" });
     products.Add(new ProductDTO() { Id = 2, Name = "Product Two" });
     products.Add(new ProductDTO() { Id = 3, Name = "Product Three" });
     products.Add(new ProductDTO() { Id = 4, Name = "Child One", Parent=1 });
     products.Add(new ProductDTO() { Id = 5, Name = "Child Two", Parent = 2 });
     products.Add(new ProductDTO() { Id = 6, Name = "Child One", Parent = 1 });
    
    var ordered = products
                    .Where(p => p.Parent == null)
                    .OrderBy(p=> p.Id)
                    .Select(p => products
                        .Where(c => c.Parent == p.Id)
                        .OrderBy(c => c.Id))
                    .ToList();
    

    【讨论】:

    • 我可能会出现代码盲...但是#5 应该是Parent = 1 并且#6 应该是Parent = 2
    • 以上只是一个例子。父级可以是数据中的任何内容。只要它是父母的有效 ID。
    • 啊,是的,抱歉:澄清一下,我并不是说它会影响您答案的有效性……(它只会整理示例数据)。
    • :(我没有得到预期的结果。
    【解决方案3】:

    你可以这样做:

    list.ForEach(item => 
                {
                    if (item.Parent == null)
                    {
                        orderedList.Add(item);
                        orderedList.AddRange(list.Where(child => child.Parent == item.Id));
                    }
                });
    

    【讨论】:

      【解决方案4】:

      我不知道它是否更干净,但如果你想要一个独特的 linq 指令,你可以试试这个:

      var result = GetProductList().Where(p => p.Parent == null)
                                   .SelectMany(p => list.Where(c => c.Parent == p.Id)
                                                        .Concat(new[] { p })
                                                        .OrderBy(c => c.Parent.HasValue)
                                                        .ThenBy(c => c.Id)
                                                        .ToList())
                                   .ToList();
      

      【讨论】:

        【解决方案5】:

        您应该为产品一和产品二添加一个 ParentId,这样会更容易解决。 如果父母一是 1,父母二是 2,只做这个

        var result = parents.OrderBy(x => x.Parent).ThenBy(x => x.Id);
        

        【讨论】:

        • 不幸的是我不能这样做。数据库已经存在,并且要求顶级父对象的父 id 为 null。
        【解决方案6】:

        也许以这种方式使用 linq:

        var groupList = from c in products
                        where c.Parent.HasValue
                        group c by c.Parent into r
                        join p in products on r.Key equals p.Id
                        orderby p.Name
                        select new { Parent = p, Children = r };
        

        【讨论】:

          【解决方案7】:

          这是非常简单和复杂的方式,在'res'变量中你会看到这种情况 - parent1 > child.1.1 > child.1.2 > parent2 > child.2.1 > child.2.2 > child.2.3 > parent3:

                  //items is a list of unsorted objects
                 
                  var res = items.OrderBy(x =>
                  {
                      if (x.ParentId == null)
                          return x.Id;
                      else
                          return x.ParentId;
                  }).ThenBy(t => t.Id);
          

          【讨论】:

          • 这只是重复了this answer,但让它变得不必要的复杂。
          • @Gert 它不会重复。我以前没有看到这个答案。有一些尊重,null 是字符串,他最后将 sting 转换为 int,不是其他变量也相同,但技术相似。请仔细看
          • 差异无关紧要。如果您没有看到只会让事情变得更糟的其他答案。在考虑是否有任何真正要添加的新内容时,您应该查看现有答案。
          猜你喜欢
          • 1970-01-01
          • 2014-04-28
          • 1970-01-01
          • 1970-01-01
          • 2015-06-27
          • 2016-11-20
          • 1970-01-01
          • 1970-01-01
          • 2016-01-17
          相关资源
          最近更新 更多