Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I sort a list and its children and their children using linq?

Tags:

c#

linq

I have a parent child relationship, something like:

public class MyType {

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

}

I would like to select the list so that each level is in order.

I can do this easily for the top level:

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

But how do I do it for every set of Children?

The end result would be the list or type with all its children, and there children (and so on) all sorted correctly by Order.

Thanks.

like image 433
shenku Avatar asked Jan 16 '23 13:01

shenku


2 Answers

You can do Recursive Order by adding one method to MyType like this:

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());
    }
} 
like image 177
cuongle Avatar answered Feb 18 '23 11:02

cuongle


You can keep the children sorted if you use a SortedList as your underlying children collection. Then you can expose the Values property to get the values. Just key the items by their order when you add to the list.

e.g.,

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

Otherwise, you'd probably want to sort the lists recursively. Using LINQ wouldn't be appropriate here. At best, LINQ would allow you to iterate over the children in a sorted order but it doesn't actually sort the underlying list unless you replace the list instance with the sorted version. If the underlying list has a Sort() method (which the generic List<T> has), then use that.

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

Starting off with a sorted list would be a lot easier however.

like image 44
Jeff Mercado Avatar answered Feb 18 '23 09:02

Jeff Mercado