List 按层次结构排序

问题描述:

一个List<T>, T 的基本定义如下Data,要求实现按照层次结构排序,即排序结果如下:

L1

 L1.1

   L1.1.1

   L1.1.3

 L1.2

   L1.2.1

   L1.2.2

 L1.3

L4

 L4.1


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

namespace TestProject
{
    public class Data
    {
        public Data()
        {

        }

        public Data(string id ,string parentId,string name)
        {
            Id = id;
            ParentId = parentId;
            Name = name;
                    
        }

        public string Id
        {
            get;
            set;
        }

        public string Name
        {
            get;
            set;
        }

        public string ParentId
        {
            get;
            set;
        }

    

     

    }
}

一个简单的实现是:通过计算各个list Item的 nodepath 来实现, 为了简单,增加了一个Path属性,如果不想修改原来Data定义,可以投影出一个新的对象来。

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
using System.Linq;

namespace TestProject
{
    [TestClass]
    public class UnitTest1
    {
        private readonly Random _rng = new Random();
        private const string _chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

        [TestMethod]
        public void TestMethod1()
        {
            List<Data> list = GenerateData();
            bool allUnique=  list.TrueForAll(p=>list.Count(c=>c.Id ==p.Id)==1  );
            Console.WriteLine("all id unique!");
            list.ForEach(p => GetDept(list, p));

            //foreach (var item in list)
            //{
            //    Console.WriteLine("id:{0} name :{2} ,depth:{1}", item.Id, item.Depth,item.Name);
            //}

            Console.WriteLine();
            Console.WriteLine("======orginal with node path==============");

            var roots = list.FindAll(p => string.IsNullOrEmpty(p.ParentId));
            //计算Node Path
            roots.ForEach(p => CreateNodePath(p, string.Empty, list));

            foreach (var item in list)
            {
                Console.WriteLine("id:{0} ,depth:{1},path ={2} name = {3}", item.Id, item.Depth, item.Path, item.Name);
            }

            Console.WriteLine();
            Console.WriteLine("shuffled");
        
            // 把list 以随机顺序排列
            Shuffle<Data>(list);
            foreach (var item in list)
            {
                Console.WriteLine("id:{0} ,depth:{1},path ={2} name = {3}", item.Id, item.Depth, item.Path, item.Name);
            }
            Console.WriteLine();
            Console.WriteLine("after sort by depth====");
            //按层次排序
            list.Sort((p1, p2) => string.Compare(p1.Path, p2.Path));

            foreach (var item in list)
            {
                Console.WriteLine("id:{0} ,depth:{1},path ={2} name = {3}", item.Id, item.Depth, item.Path, item.Name);
            }
            return;
        }


        int GetDept(List<Data> list, Data data)
        {
            if (data == null)
                return -1;
            if (data.ParentId == null)
            {
                data.Depth = 1;
                //data.Path = data.Id;
                //return 1;
            }
            else
            {
                int depth = GetDept(list, list.FirstOrDefault(p => p.Id == data.ParentId));
                data.Depth= depth + 1;
              
               // data.Path = string.Compare("{0}.1", data.Depth);
            }
            return data.Depth;
        }

     

        void CreateNodePath(Data rootNode ,string startPath,List<Data> list)  
        {
            rootNode.Path = string.Format("{0}.{1}", startPath, rootNode.Id);
            startPath = rootNode.Path;
            var subnodes = list.FindAll(p => p.ParentId == rootNode.Id);
            foreach (var sub in subnodes)
            {
                CreateNodePath(sub, startPath, list);
            }
        }


        List<Data> GenerateData()
        {

            var l1 = new Data(RandomString(8), null, RandomString(8) + "(1)");
            var l1_1 = new Data(RandomString(8), l1.Id, RandomString(8) + "(1.1)");
            var l1_2 = new Data(RandomString(8), l1.Id, RandomString(8) + "(1.2)");

            ///
            var l2 = new Data(RandomString(8), null, RandomString(8) + "(2)");
            var l2_1 = new Data(RandomString(8), l2.Id, RandomString(8) + "(2.1)");
            var l2_2 = new Data(RandomString(8), l2.Id, RandomString(8) + "(2.2)");
                var l_2_2_1 = new Data(RandomString(8), l2_2.Id, RandomString(8) + "(2.2.1)");
                var l_2_2_2= new Data(RandomString(8), l2_2.Id, RandomString(8) + "(2.2.2)");
            var l2_3 = new Data(RandomString(8), l2.Id, RandomString(8) + "(2.3)");

            

            var l3 = new Data(RandomString(8), null, RandomString(8) + "(3)");
            var l3_1 = new Data(RandomString(8), l3.Id, RandomString(8) + "(3.1)");

            var l4 = new Data(RandomString(8), null, RandomString(8) + "(4)");

            ///
            var l5 = new Data(RandomString(8), null, RandomString(8) + "(5)");
            var l5_1 = new Data(RandomString(8), l5.Id, RandomString(8) + "(5.1)");
                var l5_1_1 = new Data(RandomString(8), l5_1.Id, RandomString(8) + "(5.1.1)");
                var l5_1_2 = new Data(RandomString(8), l5_1.Id, RandomString(8) + "(5.1.2)");
            
            var l5_2 = new Data(RandomString(8), l5.Id, RandomString(8) + "(5.2)");



            var list = new List<Data>
            {
                l1,
                    l1_1,
                    l1_2

                ,l2,
                    l2_1,
                    l2_2,
                       l_2_2_1,
                       l_2_2_2,
                    l2_3

               , l3
               ,l3_1,

                l4

                ,l5
                    ,l5_1
                        ,l5_1_1
                        ,l5_1_2
                    ,l5_2
            };



            return list;

        }
        private string RandomString(int size)
        {
            char[] buffer = new char[size];

            for (int i = 0; i < size; i++)
            {
                buffer[i] = _chars[_rng.Next(_chars.Length)];
            }
            return new string(buffer);
        }

        public static void Shuffle<T>( IList<T> list)
        {
            int n = list.Count;
            Random rnd = new Random();
            while (n > 1)
            {
                int k = (rnd.Next(0, n) % n);
                n--;
                T value = list[k];
                list[k] = list[n];
                list[n] = value;
            }
        }

    }
}


结果如下:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值