📅  最后修改于: 2023-12-03 15:17:19.866000             🧑  作者: Mango
LINQ 分类运算符可以将一个序列分为多个组,对每个组进行操作,最后合并起来返回一个新的序列。分类运算符包括 GroupBy
、ToLookup
和 Join
。此外,LINQ 还提供了一个分类运算符的撤销操作 GroupBy
、ToLookup
的撤销操作 GroupBy
。
GroupBy
方法将序列分组并返回一个序列,每个组由具有相同键的元素组成。GroupBy
方法有多个重载形式,其中最常用的一种重载形式如下:
public static IEnumerable<IGrouping<TKey, TSource>> GroupBy<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector
);
上述重载形式按照 keySelector 返回的键进行分组,返回一个元素为 IGrouping<TKey, TSource>
的序列。其中 IGrouping<TKey, TSource>
接口表示一个具有公共键的元素序列,并为该键提供只读访问权限。
示例:
int[] numbers = { 1, 2, 3, 4, 5, 6 };
var groups = numbers.GroupBy(n => n % 2 == 0);
foreach (var group in groups)
{
Console.WriteLine("Even numbers: {0}", group.Key);
foreach (var number in group)
{
Console.WriteLine(number);
}
}
输出:
Even numbers: False
1
3
5
Even numbers: True
2
4
6
ToLookup
方法与 GroupBy
方法类似,都是将序列分组,但 ToLookup
方法返回的是一个 ILookup<TKey, TElement>
对象,它类似于一个字典,可以通过键来访问元素序列。
ToLookup
方法有多个重载形式,其中最常用的一种重载形式如下:
public static ILookup<TKey, TSource> ToLookup<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector
);
示例:
int[] numbers = { 1, 2, 3, 4, 5, 6 };
var lookup = numbers.ToLookup(n => n % 2 == 0);
foreach (var group in lookup)
{
Console.WriteLine("Even numbers: {0}", group.Key);
foreach (var number in group)
{
Console.WriteLine(number);
}
}
输出:
Even numbers: False
1
3
5
Even numbers: True
2
4
6
Join
方法将两个序列内的元素进行关联,返回一个新的序列。Join
方法有多个重载形式,其中最常用的一种重载形式如下:
public static IEnumerable<TResult> Join<TOuter, TInner, TKey, TResult>(
this IEnumerable<TOuter> outer,
IEnumerable<TInner> inner,
Func<TOuter, TKey> outerKeySelector,
Func<TInner, TKey> innerKeySelector,
Func<TOuter, TInner, TResult> resultSelector
);
上述重载形式根据 outerKeySelector 和 innerKeySelector 返回的键将两个序列内的元素进行关联,并根据 resultSelector 返回的结果合并为一个新的序列。
示例:
var students = new List<Student>
{
new Student { Id = 1, Name = "Alice" },
new Student { Id = 2, Name = "Bob" },
new Student { Id = 3, Name = "Charlie" }
};
var scores = new List<Score>
{
new Score { StudentId = 1, Course = "Math", Grade = 90 },
new Score { StudentId = 1, Course = "English", Grade = 85 },
new Score { StudentId = 2, Course = "Math", Grade = 80 },
new Score { StudentId = 2, Course = "English", Grade = 75 }
};
var result = students.Join(scores,
student => student.Id,
score => score.StudentId,
(student, score) => new { student.Name, score.Course, score.Grade });
foreach (var item in result)
{
Console.WriteLine("{0} {1} {2}", item.Name, item.Course, item.Grade);
}
输出:
Alice Math 90
Alice English 85
Bob Math 80
Bob English 75
LINQ 提供了一个 ToEnumerable
扩展方法,可以将实现了 IGrouping<TKey, TSource>
接口的序列转换为一个普通的序列。
示例:
int[] numbers = { 1, 2, 3, 4, 5, 6 };
var groups = numbers.GroupBy(n => n % 2 == 0);
var result = groups.SelectMany(group => group);
foreach (var number in result)
{
Console.WriteLine(number);
}
输出:
1
3
5
2
4
6
注意:上述代码中 SelectMany
方法用来将一个元素为 IGrouping<TKey, TSource>
的序列转换为一个普通的序列。