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

C#在LINQ中使用GroupBy

程序员文章站 2022-09-17 11:46:11
一、先准备要使用的类:1、person类:class person { public string name { set; get; } public int age { set; ge...

一、先准备要使用的类:

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;

以上的意思可以这样理解:从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

四、第三种用法:

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

官方释义:根据指定的键选择器函数对序列中的元素进行分组,并且通过使用指定的函数对每个组中的元素进行投影。

这个比第一种用法多了一个elementselector,第一种用法是对集合本身按照tkey分组,并将自己(tsource)添加到分组内,而当前的用法则可以选择自己想要添加到分组内的元素类型。

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

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

以上代码是按照p.gender进行分组,并将p.name作为组内的元素。

输出结果如下:

C#在LINQ中使用GroupBy

其等价的linq语句为:

var groups = from p in personlist
       group p.name by p.gender;

五、第四种用法:

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

官方释义:根据指定的键选择器函数对序列中的元素进行分组,并且从每个组及其键中创建结果值。

这个跟之前的用法都不同,之前的用法都是将结果进行分组,并返回igrouping<tkey,tsource>对象,而当前用法则是返回自己定义的类型(tresult),在返回自己定义类型之前,将会传入两个参数,一个是tkey,为分组时指定的对象,另外一个则是ienumerable<tsource>,为分组后的内部对象集合。

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

string getpersoninfo(string gender, ienumerable<person> persons)
      {
        string result = $"{gender}:\t";
        foreach (var p in persons)
        {
          result += $"{p.name},{p.age}\t";
        }
        return result;
      }
      var results = personlist.groupby(p => p.gender,(g, ps) => getpersoninfo(g,ps));
      foreach (var result in results)
      {
        console.writeline(result);
      }

getpersoninfo为局部方法,见于c#7.0及以上。

以上代码将分组后的内容(一个是tkey,为p.gender,另外一个是ienumerable<tsource>,为ienumerable<person>)作为字符串输出,因此,将返回的类型为字符串集合。

输出结果如下:

C#在LINQ中使用GroupBy

其等价的linq语句为:

      var results = from p in personlist
             group p by p.gender into pgroup
             select getpersoninfo(pgroup.key, pgroup);

六、第五种用法:

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

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

与第三种用法基本相同,只是多了一个相等比较器,用于分组的依据。

使用第二种用法的personlist及personequalitycomparer,编写客户端实验代码如下:

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

以上代码的分组依据是person,personequalitycomparer则是作为person分组的比较器,每个组内为一个匿名类型集合。

输出结果如下:

C#在LINQ中使用GroupBy

七、第六种用法:

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

官方释义:根据指定的键选择器函数对序列中的元素进行分组,并且从每个组及其键中创建结果值。通过使用指定的比较器对键进行比较。

与第四种用法基本相同,只是多了一个相等比较器,用于分组的依据。

使用第二种用法的personlist及personequalitycomparer,编写客户端实验代码如下:

string getpersoninfo(person person, ienumerable<person> persons)
      {
        string result = $"{person.tostring()}:\t";
        foreach (var p in persons)
        {
          result += $"{p.age},{p.gender}\t";
        }
        return result;
      }
      var results = personlist.groupby(p => p, (p, ps) => getpersoninfo(p, ps),new personequalitycomparer());
      foreach (var result in results)
      {
        console.writeline(result);
      }

以上代码的分组依据是person,personequalitycomparer则是作为person分组的比较器,每个组内为一个person集合,并将返回类型为string的字符串输出。

输出结果如下:

C#在LINQ中使用GroupBy

八、第七种用法:

public static ienumerable<tresult> groupby<tsource, tkey, telement, tresult>(this ienumerable<tsource> source, func<tsource, tkey> keyselector, func<tsource, telement> elementselector, func<tkey, ienumerable<telement>, tresult> resultselector);

官方释义:根据指定的键选择器函数对序列中的元素进行分组,并且从每个组及其键中创建结果值。通过使用指定的函数对每个组的元素进行投影。

与第四种方法很类似,只是对分组内的元素进行选择,原有为tsource,现改为telement。

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

string getpersoninfo(string gender, ienumerable<string> names)
      {
        string result = $"{gender}:\t";
        foreach (var name in names)
        {
          result += $"{name}\t";
        }
        return result;
      }
      var results = personlist.groupby(p => p.gender, (p=>p.name) ,(g, ns) => getpersoninfo(g, ns));
      foreach (var result in results)
      {
        console.writeline(result);
      }

以上代码将使用gender分组,并将分组后的信息组合成一条字符串,并输出到控制台。

输出结果如下:

C#在LINQ中使用GroupBy

九、第八种用法:

public static ienumerable<tresult> groupby<tsource, tkey, telement, tresult>(this ienumerable<tsource> source, func<tsource, tkey> keyselector, func<tsource, telement> elementselector, func<tkey, ienumerable<telement>, tresult> resultselector, iequalitycomparer<tkey> comparer);

官方释义: 根据指定的键选择器函数对序列中的元素进行分组,并且从每个组及其键中创建结果值。通过使用指定的比较器对键值进行比较,并且通过使用指定的函数对每个组的元素进行投影。

与第七种用法基本相同,只是多了一个相等比较器,用于分组的依据。

使用第二种用法的personlist及personequalitycomparer,编写客户端实验代码如下:

var results = personlist.groupby(p => p, (p=>new { p.age,p.gender}),
        (p, ns) => 
        {
          string result = $"{p.tostring()}:\t";
          foreach (var n in ns)
          {
            result += $"{n.age},{p.gender}\t";
          }
          return result;
        },new personequalitycomparer());
      foreach (var result in results)
      {
        console.writeline(result);
      }

以上代码将使用person分组,使用person比较器作为分组的依据,并将分组后的信息组合成一条字符串,并输出到控制台。

输出结果如下:

C#在LINQ中使用GroupBy

以上就是c#在linq中使用groupby的详细内容,更多关于c#使用groupby的资料请关注其它相关文章!

相关标签: C# LINQ GroupBy