C#的GroupBy方法是如何工作的

前言:先贴结果

 

 

 

GroupBy方法是如何工作的?

一、准备6个待分组的学生对象

 

class student
    {
        public string name;//姓名
        public int grade;//年级

        public student(string name, int grade)
        {
            this.name = name;
            this.grade = grade;
        }
    }
List<student> students = new List<student>();
            for (int i = 0; i < 3; i++)
            {
                students.Add(new student("学生" + i, 1));
            }
            for (int i = 0; i < 3; i++)
            {
                students.Add(new student("学生" + (i+3), 2));
            }

其中有3个1年级,3个2年级

二、准备分组比较值产生器

static int getGrade(student stu)
        {
            Console.WriteLine("分组关键字->\t该学生的年级:" + stu.grade);
            return stu.grade;
        }

分组方法将会调用此方法,得到分组依据

三、准备分组比较器

//学生年级相等比较器,如果分组关键字使用了学生对象,那么这里就可以用学生的其他属性进行相等比较,比如学生ID
    class studentComparer : IEqualityComparer<int>
    {
     //判断关键字是否相等,当然也可以是大于,平方,等任意规则
        public bool Equals(int x, int y)
        {
            if (x==y)
            {

                Console.WriteLine("比较器->\t学生年级相等:" + x + "年级");
                return true;
            }
            else
            {
                Console.WriteLine("学生年级不相等");
                return false;
            }
        }

        public int GetHashCode(int x)
        {
            int code = x.GetHashCode();
            return code.GetHashCode();
        }
    }

分组比较器将会对分组关键字进行比较,得到分组

四、GroupBy()分组器

//给GroupBy传入分组方法,ToList()执行分组时,程序对元素集中的每个元素调用"相等比较器"进行分组
            //得到一个包含几个分组对象IGrouping的枚举对象IEnumerable
            //每个分组对象IGrouping的属性是:(分组键值,分组元素集)
            //因此GroupBy方法属于js中的高级方法,就像map,reduce等
            //可以自定义"相等比较器"IEqualityComparer,自定义相等判断规则
            IEnumerable<IGrouping<int,student>> d = students.GroupBy<student, int>(getGrade,new studentComparer()).ToList();

分组器将会采用一个尽可能减少比较次数的算法,使用比较器分组关键字比较

在这个例子中,6个学生分两组只进行了4次比较,第一直觉是应该会用5次比较

五、分组结果展示

foreach (IGrouping<int,student> item in d)
           {
               Console.WriteLine(item.Key+"年级:");
               foreach (student stu in item)
               {
                   Console.WriteLine("\t名字:" + stu.name);
               }

           }
           Console.WriteLine("系统的比较方法很厉害,只用4次比较,将6个元素分成了2组,采用2分法的方式似乎可以");
           Console.ReadLine();

六、完整代码

class Program
    {
        static void Main(string[] args)
        {
            //6个学生
            List<student> students = new List<student>();
            for (int i = 0; i < 3; i++)
            {
                students.Add(new student("学生" + i, 1));
            }
            for (int i = 0; i < 3; i++)
            {
                students.Add(new student("学生" + (i+3), 2));
            }
           //var d = students.GroupBy<student,int>(t => t.grade);//对studentList按照ClassCode分组

            //给GroupBy传入分组方法,ToList()执行分组时,程序对元素集中的每个元素调用"相等比较器"进行分组
            //得到一个包含几个分组对象IGrouping的枚举对象IEnumerable
            //每个分组对象IGrouping的属性是:(分组键值,分组元素集)
            //因此GroupBy方法属于js中的高级方法,就像map,reduce等
            //可以自定义"相等比较器"IEqualityComparer,自定义相等判断规则
            IEnumerable<IGrouping<int,student>> d = students.GroupBy<student, int>(getGrade,new studentComparer()).ToList();
           foreach (IGrouping<int,student> item in d)
           {
               Console.WriteLine(item.Key+"年级:");
               foreach (student stu in item)
               {
                   Console.WriteLine("\t名字:" + stu.name);
               }

           }
           Console.WriteLine("系统的比较方法很厉害,只用4次比较,将6个元素分成了2组,采用2分法的方式似乎可以");
           Console.ReadLine();
        }

        static int getGrade(student stu)
        {
            Console.WriteLine("分组关键字->\t该学生的年级:" + stu.grade);
            return stu.grade;
        }
    }

    class student
    {
        public string name;//姓名
        public int grade;//年级

        public student(string name, int grade)
        {
            this.name = name;
            this.grade = grade;
        }
    }

    //学生年级相等比较器,如果分组关键字使用了学生对象,那么这里就可以用学生的其他属性进行相等比较,比如学生ID
    class studentComparer : IEqualityComparer<int>
    {

        public bool Equals(int x, int y)
        {
            if (x==y)
            {

                Console.WriteLine("比较器->\t学生年级相等:" + x + "年级");
                return true;
            }
            else
            {
                Console.WriteLine("学生年级不相等");
                return false;
            }
        }

        public int GetHashCode(int x)
        {
            int code = x.GetHashCode();
            return code.GetHashCode();
        }
    }

 

posted @ 2021-03-11 22:25  ggtc  阅读(708)  评论(0编辑  收藏  举报
//右下角目录