简体   繁体   中英

Order list by parent and child items

I have a list of products that have to be ordered by parent then all children of that parent, then next parent, etc.

Product One
    Child One
    Child Two
Product Two
    Child One

These products are all in one table with a parent id field, the child products have a parent id but the parent items can have a null parent (indicating that product is a top level product)

样品表

I was thinking something like the following:

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

Any suggestions on how I would do this a little cleaner?

Given "Parent" is nullable property (assuming nullable int here). Following should give you parent-child related ordered list:

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

you could try something like that. Assuming parent is a nullable:

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

if its a string:

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

You could do it this way:

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

I don't know if it's more cleaner but if you want a unique linq instruction you can try this :

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

You should add a ParentId to the Product One and Product two, and the, will be easier to solve it. If Parent One is 1, and Parent Two is 2, only do this

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

Maybe using linq this way:

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

It's very easy and complicated way, In 'res' variable you'll see this kind of situation - 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);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM