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.