C# linq的group by使用

首先创建实体类

class Person
    {
        public string Name { set; get; }
        public int Age { set; get; }
        public string Gender { set; get; }
        public override string ToString() => Name;
    }

创建测试数据

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",
            }
        };
  1. 第一种写法
 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}");
                }
            }
            Console.ReadKey();

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

因为groups返回的类型为IEnumerable<IGouping<TKey,TSource>>,因此以上返回的类型为IEnumerable<IGouping<string,Person>>。

IGouping<string,Person>是已经分组后的集合,内部集合元素为Person,且IGouping有一个Key属性,类型为string(指的是Gender属性类型),用于分组的标识。
其等价的LINQ语句为:

var groups = from p in personList
             group p by p.Gender;
  1. 第二种写法
public static IEnumerable<IGrouping<TKey, TSource>> GroupBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer);

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

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

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

修改测试数据

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类,并运用了自己定义的Person类相同比较器,只要Name相同,就分为一组
3. 第三种写法

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.Name,(p)=> { return p; });
            foreach (var group in groups)
            {
                Console.WriteLine(group.Key.ToString());
                foreach (var person in group)
                {
                    Console.WriteLine($"\t{person.Age},{person.Gender}");
                }
            }
            Console.ReadKey();
  1. 第四种写法
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,为分组后的内部对象集合。

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

在这里插入图片描述
其等价的LINQ语句为:

var results = from p in personList
              group p by p.Gender into pGroup
              select GetPersonInfo(pGroup.Key, pGroup);
  1. 第五种写法
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);

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

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

  1. 第六种写法
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);

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

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

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);
            }
  1. 第七种写法
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);
            }
            Console.ReadKey();
  1. 第八种写法
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);

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

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

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);
            }
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C#使用LINQ进行分组(group by)操作有多种方式。引用和引用展示了两种常见的方法。 第一种方法是使用LINQ查询表达式。在查询表达式中,我们可以使用`group by`子句来指定要分组的属性,然后使用`into`子句将结果存储在一个临时变量中。下面是一个示例: ```csharp var results = from p in persons group p.car by p.PersonId into g select new { PersonId = g.Key, Cars = g.ToList() }; ``` 在这个示例中,我们将`persons`集合按照`PersonId`属性进行分组,并将每个分组的`car`属性收集到一个列表中。结果将包含每个分组的`PersonId`和对应的`Cars`列表。 第二种方法是使用LINQ的函数形式。在函数形式中,我们可以使用`GroupBy`方法,该方法接受三个参数:分组的属性、分组的元素和一个选择器函数。此外,我们还需要使用`ToList`方法将结果转换为列表。下面是一个示例: ```csharp var results = persons.GroupBy(p => p.PersonId, p => p.car, (key, g) => new { PersonId = key, Cars = g.ToList() }); ``` 这个示例与前面的查询表达式示例的功能相同。我们通过`PersonId`属性进行分组,将每个分组的`car`属性收集到一个列表中,并创建一个包含`PersonId`和`Cars`属性的匿名对象。 总而言之,以上就是在C#使用LINQ进行分组操作的两种常见方法。您可以根据个人喜好和项目需求选择适合的方法。引用提供了更多关于C#使用LINQ的`GroupBy`操作的详细信息和示例,供您进一步了解和学习。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [C#Linq中的GroupBy](https://blog.csdn.net/q__y__L/article/details/125997669)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [C#LINQ使用GroupBy](https://download.csdn.net/download/weixin_38610717/12721697)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值