📜  LINQ |分类运算符|撤销(1)

📅  最后修改于: 2023-12-03 15:17:19.866000             🧑  作者: Mango

LINQ 分类运算符 | 撤销

概述

LINQ 分类运算符可以将一个序列分为多个组,对每个组进行操作,最后合并起来返回一个新的序列。分类运算符包括 GroupByToLookupJoin。此外,LINQ 还提供了一个分类运算符的撤销操作 GroupByToLookup 的撤销操作 GroupBy

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

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 方法将两个序列内的元素进行关联,返回一个新的序列。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
GroupBy 撤销

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> 的序列转换为一个普通的序列。