欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

[C#] LINQ之GroupBy

程序员文章站 2022-10-17 09:28:04
声明:本文为www.cnc6.cn原创,转载时请注明出处,谢谢! 一、先准备要使用的类: 1、Person类: 2、准备要使用的List,用于分组(GroupBy): 二、第一种用法: 官方释义:根据指定的键选择器函数对序列中的元素进行分组。 我们要分组的集合为source,集合内每个元素的类型为T ......

声明:本文为原创,转载时请注明出处,谢谢!

一、先准备要使用的类:

1、person类:

    class person
    {
        public string name { set; get; }
        public int age { set; get; }
        public string gender { set; get; }
        public override string tostring() => name;
    }

2、准备要使用的list,用于分组(groupby):

        list<person> personlist = new list<person>
        {
            new person
            {
                name = "p1", age = 18, gender = "male"

            },
            new person
            {
                name = "p2", age = 19, gender = "male",
            },
            new person
            {
                name = "p2", age = 17,gender = "female",
            }
        };

二、第一种用法:

public static ienumerable<igrouping<tkey, tsource>> groupby<tsource, tkey>(this ienumerable<tsource> source, func<tsource, tkey> keyselector);

官方释义:根据指定的键选择器函数对序列中的元素进行分组。

我们要分组的集合为source,集合内每个元素的类型为tsource,这里第一个参数keyselector的类型为func<tsource, tkey>,用于将tsource元素按照由此委托返回的类型tkey进行分组,结果为一个已分好组的集合(集合中的集合)。

编写客户端试验代码如下:

        var groups = personlist.groupby(p => p.gender);
        foreach (var group in groups)
        {
            console.writeline(group.key);
            foreach(var person in group)
            {
                console.writeline($"\t{person.name},{person.age}");
            }
        }

以上代码指定的keyselector是person类的gender属性,因此,以上会按照gender(性别)进行分组,我们使用两个嵌套的foreach循环将分组的内容打印到控制台。

因为groups返回的类型为ienumerable<igouping<tkey,tsource>>,因此以上返回的类型为ienumerable<igouping<string,person>>。

igouping<string,person>是已经分组后的集合,内部集合元素为person,且igouping有一个key属性,类型为string(指的是gender属性类型),用于分组的标识。

输出结果如下:

[C#] LINQ之GroupBy

其等价的linq语句为:

var groups = from p in personlist
             group p by p.gender into pgroup
             select pgroup;

以上的意思可以这样理解:从personlist取出p,并对p进行分组,使用分组的依据(key)为p.gender,并将分组的结果存储到pgroup,并将分组的结果选择出来合并成一个集合。

 三、第二种用法:

public static ienumerable<igrouping<tkey, tsource>> groupby<tsource, tkey>(this ienumerable<tsource> source, func<tsource, tkey> keyselector, iequalitycomparer<tkey> comparer);

官方释义:根据指定的键选择器函数对序列中的元素进行分组,并使用指定的比较器对键进行比较。

这种比第一种方法多了一个参数,那就是一个相等比较器,目的是为了当tkey为自定义的类时,groupby能根据tkey指定的类根据相等比较器进行分组,

因此,自定义类如何进行分组,groupby是不知道的,需要自己定义自己的相等比较器。

首先,将personlist更改如下(下划线部分):

        list<person> personlist = new list<person>
        {
            new person
            {
                name = "p1", age = 18, gender = "male"

            },
            new person
            {
                name = "p1", age = 19, gender = "male",
            },
            new person
            {
                name = "p3", age = 17,gender = "female",
            }
        };

其次,增加一个相等比较器类,用于对person进行分组:

    class personequalitycomparer : iequalitycomparer<person>
    {
        public bool equals(person x, person y) => x.name == y.name;
        public int gethashcode(person obj) => obj.name.gethashcode();
    }

其中定义了如何对一个person相等性定义,只要实现iequalitycomparer<person>即可,这里以name作为person类是否相同的依据。

最后,现在我们对person类进行分组,编写客户端实验代码如下:

        var groups = personlist.groupby(p => p, new personequalitycomparer());
        foreach (var group in groups)
        {
            console.writeline(group.key.tostring());
            foreach(var person in group)
            {
                console.writeline($"\t{person.age},{person.gender}");
            }
        }

以上的分组依据是person类,并运用了自己定义的person类相同比较器,只要name相同,就分为一组,

输出结果如下:

[C#] LINQ之GroupBy

第三~八种用法,待续~