【问题标题】:Hierarchical data sorting C#分层数据排序 C#
【发布时间】:2016-07-14 21:28:57
【问题描述】:

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

实体:

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

有什么建议吗?

【问题讨论】:

  • 到目前为止你做了什么?发布您的尝试。
  • 您确定示例输出正确吗,因为 Id = 4 的项目不在其父项旁边(id = 2)?
  • 您可以将您的数据放在DataTable 中并按照本文第一部分中的方式对其进行排序:weblogs.asp.net/stevewellens/…
  • 在这里回答了类似的问题:stackoverflow.com/questions/17968069/…
  • 我猜你的班级应该是Id 而不是IDint? ParentId 而不是int ParentID。还要检查纳斯雷丁的评论。

标签: c#


【解决方案1】:

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

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

希望这会有所帮助。

【讨论】:

  • 那不只是按名称排序而不是按 ParentId 排序,因为没有同名的项目吗?
  • 那么您可能只对名称进行排序。最好的问候,
  • 我没听懂你。您的代码将按照它们在问题中显示的确切顺序列出这些项目,按名称排序...
  • 这个问题令人困惑 - 阅读上面的 cmets 线程。最好的问候,
  • 有些人被命令弄糊涂了,但它是正确的。仔细检查一下。 ;)
【解决方案2】:

试试这个 我假设第一个你想按 parentid 排序,并且在每个父母中你想按 id 排序。

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

【讨论】:

  • 我想过,但我认为这只适用于两个级别。带有Id = 5 的项目不会出现在其父项的正下方,而是出现在最后。
【解决方案3】:

试试这个递归代码

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

        }
    }
}

【讨论】:

    【解决方案4】:

    你有办法做到这一点。如您所见,我覆盖了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);
    }
    

    【讨论】:

      【解决方案5】:

      以下应该可以解决问题(并显示一些更好的性能,因为我们将层次结构保存在查找中,而不是动态搜索 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 进行排序的方法,使用一些聪明的比较器之类的方法会很有趣。

      【讨论】:

        【解决方案6】:

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

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

        【讨论】:

          猜你喜欢
          • 2013-03-28
          • 1970-01-01
          • 2011-02-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多