跳转至

投影运算⚓︎

一、投影运算方法⚓︎

在查询语法中,通过 select 关键字完成投影运算,比如:

var queryAllCustomers = from cust in customers select cust;

在方法语法中,存在标准查询运算符方法来完成这一功能,下面列出列这些方法,需要注意的是不是所有方法都有对应的查询语法关键字:

方法 说明 查询语法 链接
Select 将序列的每个元素按指定规则投影 select Enumerable.SelectQueryable.Select
SelectMany 将序列的每个元素按指定规则投影,并将结果序列合并为一个序列 多 from 子句 Enumerable.SelectManyQueryable.SelectMany
Zip 使用 2-3 个指定序列中的元素生成元组序列 × Enumerable.ZipQueryable.Zip

二、Select⚓︎

Select() 方法会将调用它的序列按照传入的函数规则返回投影结果。下例展示了查询语法与方法语法的对比使用,示例显式序列中每个单词的首字母。

List<string> words = new() { "an", "apple", "a", "day" };

// 查询语法
var query1 = from word in words
            select word.Substring(0, 1);

foreach (string s in query1)
    Console.WriteLine(s);

Console.WriteLine();

// 方法语法
var query2 = words.Select(word => word.Substring(0, 1));

foreach (string s in query2)
    Console.WriteLine(s);

/* This code produces the following output:
    a a a d
    a a a d
*/

三、SelectMany⚓︎

SelectMany() 将序列的每个元素按指定规则投影,并将结果序列合并为一个序列,在面对具有对个 from 子句时考虑使用该方法。下例展示了查询语法与方法语法的对比使用,示例显式序列中每个单词的首字母。

List<string> phrases = new() { "an apple a day", "the quick brown fox" };

// 查询语法
var query1 = from phrase in phrases
            from word in phrase.Split(' ')
            select word;

foreach (string s in query1)
    Console.Write(s + " ");

Console.WriteLine();

// 方法语法
IEnumerable<string> query2 = phrases.SelectMany(phrase => phrase.Split(' '));

foreach (string s in query2)
    Console.Write(s + " ");

/* This code produces the following output:
    an apple a day the quick brown fox
    an apple a day the quick brown fox
*/

Tip

如果你考虑使用 Select() 完成上述功能,代码如下:

IEnumerable<string[]> query = phrases.Select(phrase => phrase.Split(" "));
// 双重循环
foreach (string[] strs in query)
    foreach (string str in strs)
        Console.WriteLine(str);

四、Zip⚓︎

Zip 方法可以处理两个或更多可能是异构类型的序列,生成 元组 序列。

// An int array with 7 elements.
IEnumerable<int> numbers = new[]
{
    1, 2, 3, 4, 5, 6, 7
};
// A char array with 6 elements.
IEnumerable<char> letters = new[]
{
    'A', 'B', 'C', 'D', 'E', 'F'
};

foreach ((int number, char letter) in numbers.Zip(letters))
{
    Console.WriteLine($"Number: {number} zipped with letter: '{letter}'");
}

/* This code produces the following output:
    Number: 1 zipped with letter: 'A'
    Number: 2 zipped with letter: 'B'
    Number: 3 zipped with letter: 'C'
    Number: 4 zipped with letter: 'D'
    Number: 5 zipped with letter: 'E'
    Number: 6 zipped with letter: 'F'
*/

Warning

zip 操作生成的序列的长度永远不会长于最短序列。 numbers 和 letters 集合的长度不同,生成的序列将省略 numbers 集合中的最后一个元素,因为它没有任何要压缩的内容。