linq 按父项和子项排序列表

vmdwslir  于 8个月前  发布在  其他
关注(0)|答案(8)|浏览(75)

我有一个产品列表,必须按父排序,然后按父的所有子排序,然后按下一个父排序,等等。

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


有什么建议让我做得更干净一点吗?

uoifb46i

uoifb46i1#

你可以尝试类似的东西。假设parent是一个nullable:

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

dgsult0t

dgsult0t2#

给定“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();

字符串

6gpjuf90

6gpjuf903#

你可以这样做:

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

字符串

bq9c1y66

bq9c1y664#

我不知道它是否更干净,但如果你想要一个独特的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();

字符串

oyxsuwqo

oyxsuwqo5#

您应该为Product One和Product Two添加一个ParentId,这样会更容易解决。如果Parent One为1,Parent Two为2,则只执行此操作

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

字符串

db2dz4w8

db2dz4w86#

可以这样使用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 };

字符串

uubf1zoe

uubf1zoe7#

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

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

字符串

e5njpo68

e5njpo688#

我也有同样的问题,但我用另一种方法解决了它,没有父级限制,使用递归原则。
通过编辑由@loopedcode编写的示例,有一些用于说明目的的Product类的编辑。

public class ProductDTO
 {
     public int Id { get; set; }
     public string Name { get; set; }
     public int? Parent { get; set; }
     public override string ToString() {
         return "[" + Id + " - " + Name + "]";
     }
     public int Deep { get; set; }
 }

字符串
让我们编写一个递归函数,从给定的产品列表中构建一个有序列表

public static List<ProductDTO> GetOrderedList(List<ProductDTO> Items, int? root, int deep) {
    var result = new List<ProductDTO>();
    foreach(var item in Items.Where(x => x.Parent == root).OrderBy(x => x.Id)) {
        item.Deep = deep;
        result.Add(item);
        result.AddRange(GetOrderedList(Items, item.Id, deep + 1));
    }
    return result;
}


假设客户端代码给予我们一个完全无序的列表,只需调用根项的递归函数就可以构建有序列表

public static void Main()
{
    Console.WriteLine("Hello World");

     var products = new List<ProductDTO>();
     products.Add(new ProductDTO() { Id = 7, Name = "Child One", Parent = 3 });
     products.Add(new ProductDTO() { Id = 10, Name = "Child One", Parent = 4 });
     products.Add(new ProductDTO() { Id = 8, Name = "Child Three", Parent = 1 });
     products.Add(new ProductDTO() { Id = 9, Name = "Child Two", Parent = 2 });
     products.Add(new ProductDTO() { Id = 1, Name = "Product One" });
     products.Add(new ProductDTO() { Id = 2, Name = "Product Two" });
     products.Add(new ProductDTO() { Id = 6, Name = "Child Two", Parent = 1 });
     products.Add(new ProductDTO() { Id = 4, Name = "Child One", Parent = 1 });
     products.Add(new ProductDTO() { Id = 5, Name = "Child One", Parent = 2 });
     products.Add(new ProductDTO() { Id = 3, Name = "Product Three" });
    
    var ordered = GetOrderedList(products, null, 0);
    foreach(var item in ordered) {
        for(int i = 0; i < item.Deep; i++) {
            Console.Write("\t");
        }
        Console.Write(item.ToString());
        Console.Write("\n");
    }
    
}


下面是输出结果的打印,解决方案可以尝试here

Hello World
[1 - Product One]
    [4 - Child One]
        [10 - Child One]
    [6 - Child Two]
    [8 - Child Three]
[2 - Product Two]
    [5 - Child One]
    [9 - Child Two]
[3 - Product Three]
    [7 - Child One]

相关问题