分层数据排序C#

时间:2016-03-27 14:30:57

标签: c#

我有一个小的层次结构。例如:

实体:

public class MyClass
{
    public int ID { get; set; }
    public string Name { get; set; }
    public int ParentID { get; set; }
}

我的层次结构数据如下所示:

Id = 1  Name = Item1    ParentId = NULL
Id = 2  Name = Item2    ParentId = 1
Id = 3  Name = Item3    ParentId = 2
Id = 4  Name = Item4    ParentId = 2
Id = 5  Name = Item5    ParentId = 3

问题是我需要对子节点必须在其直接父节点之后进行排序。下面的示例必须看起来像

Id = 1  Name = Item1    ParentId = NULL
Id = 2  Name = Item2    ParentId = 1
Id = 3  Name = Item3    ParentId = 2
// the elements with parentID = 3
              Id = 5    Name = Item5    ParentId = 3
    //continue
    Id = 4  Name = Item4    ParentId = 2

任何广告?

6 个答案:

答案 0 :(得分:0)

假设您有_listMyClass个对象,请先在Name字段,然后在ParentId字段中对其进行排序,如下所示,使用LINQ:

_list.OrderBy(L=>L.Name).ThenBy(L=>L.ParentId);

希望这可能会有所帮助。

答案 1 :(得分:0)

试试这个 我假设你想要按照parentid和每个父母的顺序排序,你想按ID排序。

myClassList.OrderBy(parent=>parent.ParentId).ThenBy(parent=>parent.Id);

答案 2 :(得分:0)

试试这个递归代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            MyClass.data = new List<MyClass>() {
                new MyClass() { ID = 1,  Name = "Item1",    ParentID = null},
                new MyClass() { ID = 2,  Name = "Item2",    ParentID = 1 },
                new MyClass() { ID = 3,  Name = "Item3",    ParentID = 2 },
                new MyClass() { ID = 4,  Name = "Item4",    ParentID = 2 },
                new MyClass() { ID = 5,  Name = "Item5",    ParentID = 3 }
            };

            MyClass myClass = new MyClass();
            myClass.GetData(null, 0);
            Console.ReadLine();
        }
    }
    public class MyClass
    {
        public static List<MyClass> data = null;
        public int ID { get; set; }
        public string Name { get; set; }
        public int? ParentID { get; set; }

        public void GetData(int? id, int level)
        {
            List<MyClass> children = data.Where(x => x.ParentID == id).ToList();

            foreach (MyClass child in children)
            {
                Console.WriteLine(" {0} ID : {1}, Name : {2}, Parent ID : {3}", new string(' ',4 * level),child.ID, child.Name, child.ParentID);
                GetData(child.ID, level + 1);
            }

        }
    }
}

答案 3 :(得分:0)

在这里你有办法做到这一点。正如您所看到的,我覆盖了ToString方法,并添加了一些案例。

public class MyClass
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int? ParentId { get; set; }

    public override string ToString()
    {
        return string.Format("{0}: {1} - {2}", Id, Name, ParentId);
    }
}

class Program
{

    static void Main(string[] args)
    {
        List<MyClass> list = new List<MyClass>();
        list.Add(new MyClass { Id = 1, Name = "Item1", ParentId = null });
        list.Add(new MyClass { Id = 2, Name = "Item2", ParentId = 1 });
        list.Add(new MyClass { Id = 3, Name = "Item3", ParentId = 2 });
        list.Add(new MyClass { Id = 4, Name = "Item4", ParentId = 2 });
        list.Add(new MyClass { Id = 5, Name = "Item5", ParentId = 3 });
        list.Add(new MyClass { Id = 6, Name = "Item6", ParentId = 1 });
        list.Add(new MyClass { Id = 7, Name = "Item7", ParentId = null });
        list.Add(new MyClass { Id = 8, Name = "Item8", ParentId = 2 });
        list.Add(new MyClass { Id = 9, Name = "Item9", ParentId = 6 });
        list.Add(new MyClass { Id = 10, Name = "Item10", ParentId = 7 });

        foreach(var item in list.Where(x => !x.ParentId.HasValue).OrderBy(x => x.Id))
            ProcessItem(item, list, 0);

        Console.ReadKey();

    }

    private static void ProcessItem(MyClass item, List<MyClass> list, int level)
    {
        Console.WriteLine("{0}{1}", new string(' ', level * 2), item.ToString());
        foreach (var subitem in list.Where(x => x.ParentId == item.Id).OrderBy(x => x.Id))
            ProcessItem(subitem, list, level  + 1);
    }
}

这样的事情对你有用吗?

如果您需要实际的有序列表,请尝试以下方法:

foreach (var item in OrderList(list))
    Console.WriteLine(item.ToString());

(...)

private static List<MyClass> OrderList(List<MyClass> list)
{
    List<MyClass> orderedList = new List<MyClass>(list.Count());
    foreach (var item in list.Where(x => !x.ParentId.HasValue).OrderBy(x => x.Id))
        AddItem(item, list, orderedList);

    return orderedList;
}

private static void AddItem(MyClass item, List<MyClass> list, List<MyClass> orderedList)
{
    orderedList.Add(item);
    foreach (var subitem in list.Where(x => x.ParentId == item.Id).OrderBy(x => x.Id))
        AddItem(subitem, list, orderedList);
}

答案 4 :(得分:0)

以下应该做的伎俩(并显示一些更好的性能,因为我们在查找中保存层次结构,而不是动态搜索IEnumerable):

public List<MyClass> SortHierarchically(IEnumerable<MyClass> myClasses)
{
    if(myClasses == null)
        return new List<MyClass>();

    var myClassesByParentId = myClasses.ToLookup(mc => mc.ParentId);
    var result = new List<MyClass>(myClasses.Count());

    int? currentParentId = null;
    MyClass currentItem = myClassesByParentId[currentParentId].Single();
    result.Add(currentItem);
    currentParentId = currentItem.Id;

    if(myClassesByParentId.Contains(currentParentId))
        result.AddRange(myClassesByParentId[currentParentId].SelectMany(mc => GetAllSortedChildren(mc, myClassesByParentId)));  

    return result;
}

public List<MyClass> GetAllSortedChildren(MyClass parent, ILookup<int?, MyClass> myClassesByParentId)
{
    var result = new List<MyClass>() { parent };
    if(myClassesByParentId.Contains(parent.Id))
        retsult.AddRange(myClassesByParentId[parent.Id].SelectMany(mc => GetAllSortedChildren(mc, myClassesByParentId)));

    return result;
}

找到一种通过标准LINQ对其进行排序的方法,以及一些聪明的比较器等,将会很有趣。

答案 5 :(得分:0)

上述答案之一效果很好。这是一个通用版本。

public static class SortingMethods
{
    public static IList<T> OrderByHierarchical<T>(
        this IEnumerable<T> items,
        Func<T, string> getId,
        Func<T, string> getParentId)
    {
        if (items == null)
            return new List<T>();

        var itemsByParentId = items.ToLookup(item => getParentId(item));
        var result = new List<T>(items.Count());

        var currentParentId = "";
        var currentItem = itemsByParentId[currentParentId].Single();
        result.Add(currentItem);
        currentParentId = getId(currentItem);

        if (itemsByParentId.Contains(currentParentId))
            result.AddRange(itemsByParentId[currentParentId].SelectMany(item => GetAllSortedChildren(item, itemsByParentId, getId)));

        return result;
    }

    private static IList<T> GetAllSortedChildren<T>(T parent, ILookup<string, T> itemsByParentId, Func<T, string> getId)
    {
        var result = new List<T>() { parent };

        if (itemsByParentId.Contains(getId(parent)))
        {
            result.AddRange(itemsByParentId[getId(parent)].SelectMany(item => GetAllSortedChildren(item, itemsByParentId, getId)));
        }

        return result;
    }
}