如何使用Linq对列表及其子项和子项的子项进行排序?

4

我有一个父子关系,类似于:

public class MyType {

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

}

我希望选择列表,使得每个级别都是有序的。

对于顶层,我可以很容易地完成这个操作:

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

但是我如何为每组子元素执行此操作?

最终结果将是按顺序正确排列的所有子元素及其子元素(依此类推)的列表或类型。

谢谢。

5个回答

6
你可以通过为MyType添加以下方法来执行递归排序:
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());
    }
} 

2
如果您使用SortedList作为子项集合,就可以对子项进行排序。然后,您可以公开Values属性以获取值。只需在添加到列表时按其order键入项目即可。
例如:
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);
    }
}

否则,您可能希望递归地对列表进行排序。在这里使用LINQ是不合适的。最多,LINQ 可以让您按排序顺序迭代子项,但它并不实际对底层列表进行排序,除非您用已排序的版本替换列表实例。如果底层列表具有 Sort() 方法(泛型 List 就有这个方法),那么请使用该方法。
private List<MyType> children;
public void EnsureSorted()
{
    children.Sort();
    foreach (var child in children)
        child.EnsureSorted();
}

以已排序的列表开始会更容易一些。

1

我同意Jeff的观点,如果按照排序后的数据作为主要访问模式,那么最简单的答案就是存储已排序的数据。但是假设你真的想用Linq来实现这个功能:

首先,如果你知道你只需要两个级别的排序,你可以像这样做:

myList.Children.OrderBy(x => x.Order)
    .Select(c => c.Children.OrderBy(x => x.Order))

但是如果你真正想要的是完全递归排序,一直到底部呢?

delegate IEnumerable<MyType> RecursiveFunc(MyType data, RecursiveFunc self);
RecursiveFunc op = (data, func) => data.Children.OrderBy(x => x.Order)
    .Select(x => func(x, func));

IEnumerable<MyType> result = op(myList, op);

仅仅是写这些文字就让我的大脑感到疼痛,而且我还没有尝试运行它,所以祝你好运!归根结底,就是将一个Linq表达式(Lambda)传递给自身,以便在树形结构中进行递归应用。

0
如果最终结果只需要是一个子元素列表(而不是一个带有嵌套子元素的父元素列表),您可以使用 SelectMany
IEnumerable<Child> result  = parents
    .SelectMany(p => p.Children)
    .OrderBy(child => child.Order);

0

尝试一下

mylist.Children.OrderBy(x => x.Order).ThenBy( x => x.order).ToList();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接