本篇主要介绍标准查询运算符的常用运算功能。
通过指定第二个排序条件,您可以对每个主要排序组内的元素进行排序。
下图展示了对一系列字符执行按字母顺序排序操作的结果。
下节列出了对数据进行排序的标准查询运算符方法。
方法
| 方法名 | 说明 | C# 查询表达式语法 | 详细信息 |
|---|---|---|---|
| OrderBy | 按升序对值排序。 | orderby |
Enumerable.OrderBy Queryable.OrderBy |
| OrderByDescending | 按降序对值排序。 | orderby … descending |
Enumerable.OrderByDescending Queryable.OrderByDescending |
| ThenBy | 按升序执行次要排序。 | orderby …, … |
Enumerable.ThenBy Queryable.ThenBy |
| ThenByDescending | 按降序执行次要排序。 | orderby …, … descending |
Enumerable.ThenByDescending Queryable.ThenByDescending |
| Reverse | 反转集合中元素的顺序。 | 不适用。 |
Enumerable.Reverse Queryable.Reverse |
查询表达式语法示例
主要排序示例
主要升序排序
下面的示例演示如何在 LINQ 查询中使用 orderby 子句按字符串长度对数组中的字符串进行升序排序。
string[] words = { "the", "quick", "brown", "fox", "jumps" }; IEnumerable<string> query = from word in words orderby word.Length select word; foreach (string str in query) Console.WriteLine(str); /* 输出: the fox quick brown jumps */
主要降序排序
下面的示例演示如何在 LINQ 查询中使用 orderby descending 子句按字符串的第一个字母对字符串进行降序排序。
string[] words = { "the", "quick", "brown", "fox", "jumps" }; IEnumerable<string> query = from word in words orderby word.Substring(0, 1) descending select word; foreach (string str in query) Console.WriteLine(str); /* 输出: the quick jumps fox brown */
次要排序示例
次要升序排序
首先按字符串长度,其次按字符串的第一个字母,对字符串进行升序排序。
string[] words = { "the", "quick", "brown", "fox", "jumps" }; IEnumerable<string> query = from word in words orderby word.Length, word.Substring(0, 1) select word; foreach (string str in query) Console.WriteLine(str); /* 输出: fox the brown jumps quick */
次要降序排序
首先按字符串长度,其次按字符串的第一个字母,对字符串进行排序。
string[] words = { "the", "quick", "brown", "fox", "jumps" }; IEnumerable<string> query = from word in words orderby word.Length, word.Substring(0, 1) descending select word; foreach (string str in query) Console.WriteLine(str); /* 输出: the fox quick jumps brown */
LINQ 中的集运算是指根据相同或不同集合(或集)中是否存在等效元素来生成结果集的查询运算。
下节列出了执行集运算的标准查询运算符方法。
方法
| 方法名 | 说明 | C# 查询表达式语法 | 详细信息 |
|---|---|---|---|
| Distinct | 删除集合中的重复值。 | 不适用。 |
Enumerable.Distinct Queryable.Distinct |
| Except | 返回差集,差集指位于一个集合但不位于另一个集合的元素。 | 不适用。 |
Enumerable.Except Queryable.Except |
| 相交 | 返回交集,交集指同时出现在两个集合中的元素。 | 不适用。 |
Enumerable.Intersect Queryable.Intersect |
| 联合 | 返回并集,并集指位于两个集合中任一集合的唯一的元素。 | 不适用。 |
Enumerable.Union Queryable.Union |
比较集运算
Distinct
返回的序列包含输入序列的唯一元素。
Except
返回的序列只包含位于第一个输入序列但不位于第二个输入序列的元素。
相交
返回的序列包含两个输入序列共有的元素。
联合
返回的序列包含两个输入序列的唯一元素。
它也称为选定内容。
筛选操作的谓词指定字符必须为“A”。
下面一节列出了执行所选内容的标准查询运算符方法。
方法
| 方法名 | 说明 | C# 查询表达式语法 | 详细信息 |
|---|---|---|---|
| OfType | 根据其转换为特定类型的能力选择值。 | 不适用。 |
Enumerable.OfType Queryable.OfType |
| Where | 选择基于谓词函数的值。 | where |
Enumerable.Where Queryable.Where |
查询表达式语法示例
以下示例使用 where 子句从数组中筛选具有特定长度的字符串。
string[] words = { "the", "quick", "brown", "fox", "jumps" }; IEnumerable<string> query = from word in words where word.Length == 3 select word; foreach (string str in query) Console.WriteLine(str); /* 输出: the fox */
Boolean 值,该值指示序列中是否有一些元素满足条件或是否所有元素都满足条件。
第二个运算询问是否所有元素都为字符“A”,结果为 true。
下节列出了执行限定符运算的标准查询运算符方法。
方法
| 方法名 | 说明 | C# 查询表达式语法 | 详细信息 |
|---|---|---|---|
| 全部 | 确定是否序列中的所有元素都满足条件。 | 不适用。 |
Enumerable.All Queryable.All |
| 任意 | 确定序列中是否有元素满足条件。 | 不适用。 |
Enumerable.Any Queryable.Any |
| 包含 | 确定序列是否包含指定的元素。 | 不适用。 |
Enumerable.Contains Queryable.Contains |
还可以在不更改原始对象的情况下投影该对象。
下面一节列出了执行投影的标准查询运算符方法。
方法
| 方法名 | 说明 | C# 查询表达式语法 | 详细信息 |
|---|---|---|---|
| 选择 | 投影基于转换函数的值。 | select |
Enumerable.Select Queryable.Select |
| SelectMany | 投影基于转换函数的值序列,然后将它们展平为一个序列。 | 使用多个 from 子句 |
Enumerable.SelectMany Queryable.SelectMany |
查询表达式语法示例
选择
下面的示例使用 select 子句来投影字符串列表中每个字符串的第一个字母。
List<string> words = new List<string>() { "an", "apple", "a", "day" }; var query = from word in words select word.Substring(0, 1); foreach (string s in query) Console.WriteLine(s); /* 输出: a a a d */
SelectMany
下面的示例使用多个 from 子句来投影字符串列表中每个字符串中的每个单词。
List<string> phrases = new List<string>() { "an apple a day", "the quick brown fox" }; var query = from phrase in phrases from word in phrase.Split(' ') select word; foreach (string s in query) Console.WriteLine(s); /* 输出: an apple a day the quick brown fox */
Select 与 SelectMany
然后,SelectMany() 串联这些可枚举序列,以创建一个大的序列。
在每种情况下,假定选择器(转换)函数从每个源值中选择一个由花卉数据组成的数组。
下图描述 Select() 如何返回一个与源集合具有相同元素数目的集合。
下图描述 SelectMany() 如何将中间数组序列串联为一个最终结果值,其中包含每个中间数组中的每个值。
代码示例
这需要额外的 foreach 循环,以便枚举每个子序列中的每个字符串。
1 class Bouquet 2 { 3 public List<string> Flowers { get; set; } 4 } 5 6 static void SelectVsSelectMany() 7 { 8 List<Bouquet> bouquets = new List<Bouquet>() { 9 new Bouquet { Flowers = new List<string> { "sunflower", "daisy", "daffodil", "larkspur" }}, 10 new Bouquet { Flowers = new List<string> { "tulip", "rose", "orchid" }}, 11 new Bouquet { Flowers = new List<string> { "gladiolis", "lily", "snapdragon", "aster", "protea" }}, 12 new Bouquet { Flowers = new List<string> { "larkspur", "lilac", "iris", "dahlia" }} 13 }; 14 15 // *********** Select *********** 16 IEnumerable<List<string>> query1 = bouquets.Select(bq => bq.Flowers); 17 18 // ********* SelectMany ********* 19 IEnumerable<string> query2 = bouquets.SelectMany(bq => bq.Flowers); 20 21 Console.WriteLine("Results by using Select():"); 22 // 注意这里额外的foreach循环 23 foreach (IEnumerable<String> collection in query1) 24 foreach (string item in collection) 25 Console.WriteLine(item); 26 27 Console.WriteLine("\nResults by using SelectMany():"); 28 foreach (string item in query2) 29 Console.WriteLine(item); 30 31 /* 输出: 32 33 Results by using Select(): 34 sunflower 35 daisy 36 daffodil 37 larkspur 38 tulip 39 rose 40 orchid 41 gladiolis 42 lily 43 snapdragon 44 aster 45 protea 46 larkspur 47 lilac 48 iris 49 dahlia 50 51 Results by using SelectMany(): 52 sunflower 53 daisy 54 daffodil 55 larkspur 56 tulip 57 rose 58 orchid 59 gladiolis 60 lily 61 snapdragon 62 aster 63 protea 64 larkspur 65 lilac 66 iris 67 dahlia 68 */ 69 70 }
LINQ 中的分区是指将输入序列划分为两个部分的操作,无需重新排列元素,然后返回其中一个部分。
第三个操作跳过序列中的前两个元素,返回接下来的三个元素。
下面一节列出了对序列进行分区的标准查询运算符方法。
运算符
| 运算符名称 | 说明 | C# 查询表达式语法 | 详细信息 |
|---|---|---|---|
| Skip | 跳过序列中指定位置之前的元素。 | 不适用。 |
Enumerable.Skip Queryable.Skip |
| SkipWhile | 基于谓词函数跳过元素,直到元素不符合条件。 | 不适用。 |
Enumerable.SkipWhile Queryable.SkipWhile |
| Take | 获取序列中指定位置之前的元素。 | 不适用。 |
Enumerable.Take Queryable.Take |
| TakeWhile | 基于谓词函数获取元素,直到元素不符合条件。 | 不适用。 |
Enumerable.TakeWhile Queryable.TakeWhile |
联接两个数据源就是将一个数据源中的对象与另一个数据源中具有相同公共属性的对象相关联。
如果你具有一个 City 对象列表,并且要查找每个城市中的所有客户,则可以使用联接运算完成此项查找。
左外部联接是指返回第一个(左侧)数据源的每个元素的联接,即使其他数据源中没有关联元素。
下图显示了一个概念性视图,其中包含两个集合以及这两个集合中的包含在内部联接或左外部联接中的元素。
方法
| 方法名 | 说明 | C# 查询表达式语法 | 详细信息 |
|---|---|---|---|
| 联接 | 根据键选择器函数联接两个序列并提取值对。 | join … in … on … equals … |
Enumerable.Join Queryable.Join |
| GroupJoin | 根据键选择器函数联接两个序列,并对每个元素的结果匹配项进行分组。 | join … in … on … equals … into … |
Enumerable.GroupJoin Queryable.GroupJoin |
其他技术请参阅
分组是指将数据分到不同的组,使每组中的元素拥有公共的属性。
每个组的键是字符。
下一节列出了对数据元素进行分组的标准查询运算符方法。
方法
| 方法名 | 说明 | C# 查询表达式语法 | 详细信息 |
|---|---|---|---|
| GroupBy | IGrouping<TKey,TElement> 对象表示。 |
group … by或 group … by … into …
|
Enumerable.GroupBy Queryable.GroupBy |
| ToLookup | Lookup<TKey,TElement>(一种一对多字典)。 | 不适用。 | Enumerable.ToLookup |
查询表达式语法示例
下列代码示例根据奇偶性,使用 group by 子句对列表中的整数进行分组。
List<int> numbers = new List<int>() { 35, 44, 200, 84, 3987, 4, 199, 329, 446, 208 }; IEnumerable<IGrouping<int, int>> query = from number in numbers group number by number % 2; foreach (var group in query) { Console.WriteLine(group.Key == 0 ? "\nEven numbers:" : "\nOdd numbers:"); foreach (int i in group) Console.WriteLine(i); } /* 输出: Odd numbers: 35 3987 199 329 Even numbers: 44 200 84 4 446 208 */
其他技术请参阅
- System.Linq
- 标准查询运算符概述 (C#)
- group 子句
- 如何:创建嵌套组
- 如何:按扩展名对文件进行分组 (LINQ) (C#)
- 如何:对查询结果进行分组
- 如何:对分组操作执行子查询
- 如何:使用组将一个文件拆分成多个文件 (LINQ) (C#)
生成是指创建新的值序列。
下面一节列出了执行生成的标准查询运算符方法。
方法
| 方法名 | 说明 | C# 查询表达式语法 | 详细信息 |
|---|---|---|---|
| DefaultIfEmpty | 用默认值单一实例集合替换空集合。 | 不适用。 |
Enumerable.DefaultIfEmpty Queryable.DefaultIfEmpty |
| 空 | 返回一个空集合。 | 不适用。 | Enumerable.Empty |
| 范围 | 生成包含数字序列的集合。 | 不适用。 | Enumerable.Range |
| Repeat | 生成包含一个重复值的集合。 | 不适用。 | Enumerable.Repeat |
两个序列,其相应元素相等且具有被视为相等的相同数量的元素。
方法
| 方法名 | 说明 | C# 查询表达式语法 | 更多信息 |
|---|---|---|---|
| SequenceEqual | 通过以成对方式比较元素确定两个序列是否相等。 | 不适用。 |
Enumerable.SequenceEqual Queryable.SequenceEqual |
元素运算从序列中返回唯一、特定的元素。
下节列出了执行元素运算的标准查询运算符方法。
方法
| 方法名 | 说明 | C# 查询表达式语法 | 详细信息 |
|---|---|---|---|
| ElementAt | 返回集合中指定索引处的元素。 | 不适用。 |
Enumerable.ElementAt Queryable.ElementAt |
| ElementAtOrDefault | 返回集合中指定索引处的元素;如果索引超出范围,则返回默认值。 | 不适用。 |
Enumerable.ElementAtOrDefault Queryable.ElementAtOrDefault |
| First | 返回集合的第一个元素或满足条件的第一个元素。 | 不适用。 |
Enumerable.First Queryable.First |
| FirstOrDefault | 如果此类元素不存在,则返回默认值。 | 不适用。 |
Enumerable.FirstOrDefault Queryable.FirstOrDefault Queryable.FirstOrDefault<TSource>(IQueryable<TSource>) |
| 上一个 | 返回集合的最后一个元素或满足条件的最后一个元素。 | 不适用。 |
Enumerable.Last Queryable.Last |
| LastOrDefault | 如果此类元素不存在,则返回默认值。 | 不适用。 |
Enumerable.LastOrDefault Queryable.LastOrDefault |
| Single | InvalidOperationException。 | 不适用。 |
Enumerable.Single Queryable.Single |
| SingleOrDefault | InvalidOperationException。 | 不适用。 |
Enumerable.SingleOrDefault Queryable.SingleOrDefault |
转换方法可更改输入对象的类型。
以下是一些示例:
-
Enumerable.AsEnumerable 方法可用于隐藏类型的标准查询运算符自定义实现。
-
Enumerable.OfType 方法可用于为 LINQ 查询启用非参数化集合。
-
Enumerable.ToLookup方法可用于强制执行即时的查询,而不是将其推迟到枚举该查询时。
方法
下表列出了执行数据类型转换的标准查询运算符方法。
名称以“To”开头的方法可枚举源集合,并将项放入相应的集合类型。
| 方法名 | 说明 | C# 查询表达式语法 | 详细信息 |
|---|---|---|---|
| AsEnumerable | IEnumerable<T> 的输入。 | 不适用。 | Enumerable.AsEnumerable |
| AsQueryable | IQueryable。 | 不适用。 | Queryable.AsQueryable |
| Cast | 将集合中的元素转换为指定类型。 | from string str in words |
Enumerable.Cast Queryable.Cast |
| OfType | 根据其转换为指定类型的能力筛选值。 | 不适用。 |
Enumerable.OfType Queryable.OfType |
| ToArray | 此方法强制执行查询。 | 不适用。 | Enumerable.ToArray |
| ToDictionary | 此方法强制执行查询。 | 不适用。 | Enumerable.ToDictionary |
| ToList | 此方法强制执行查询。 | 不适用。 | Enumerable.ToList |
| ToLookup | 此方法强制执行查询。 | 不适用。 | Enumerable.ToLookup |
查询表达式语法示例
下面的代码示例使用显式类型化的范围变量将类型转换为子类型,然后才访问仅在此子类型上可用的成员。
1 class Plant 2 { 3 public string Name { get; set; } 4 } 5 6 class CarnivorousPlant : Plant 7 { 8 public string TrapType { get; set; } 9 } 10 11 static void Cast() 12 { 13 Plant[] plants = new Plant[] { 14 new CarnivorousPlant { Name = "Venus Fly Trap", TrapType = "Snap Trap" }, 15 new CarnivorousPlant { Name = "Pitcher Plant", TrapType = "Pitfall Trap" }, 16 new CarnivorousPlant { Name = "Sundew", TrapType = "Flypaper Trap" }, 17 new CarnivorousPlant { Name = "Waterwheel Plant", TrapType = "Snap Trap" } 18 }; 19 20 var query = from CarnivorousPlant cPlant in plants 21 where cPlant.TrapType == "Snap Trap" 22 select cPlant; 23 24 foreach (Plant plant in query) 25 Console.WriteLine(plant.Name); 26 27 /* 输出: 28 29 Venus Fly Trap 30 Waterwheel Plant 31 */ 32 }
串联是指将一个序列附加到另一个序列的操作。
下图描绘了两个字符序列的串联操作。
下面一节列出了执行串联的标准查询运算符方法。
方法
| 方法名 | 说明 | C# 查询表达式语法 | 详细信息 |
|---|---|---|---|
| Concat | 连接两个序列以组成一个序列。 | 不适用。 |
Enumerable.Concat Queryable.Concat |
例如,从一个月累计的每日温度值计算出日平均温度值就是一个聚合运算。
第二个操作返回序列中的最大值。
下节列出了执行聚合运算的标准查询运算符方法。
方法
| 方法名 | 说明 | C# 查询表达式语法 | 详细信息 |
|---|---|---|---|
| 聚合 | 对集合的值执行自定义聚合运算。 | 不适用。 |
Enumerable.Aggregate Queryable.Aggregate |
| 平均值 | 计算值集合的平均值。 | 不适用。 |
Enumerable.Average Queryable.Average |
| 计数 | 对集合中元素计数,可选择仅对满足谓词函数的元素计数。 | 不适用。 |
Enumerable.Count Queryable.Count |
| LongCount | 对大型集合中元素计数,可选择仅对满足谓词函数的元素计数。 | 不适用。 |
Enumerable.LongCount Queryable.LongCount |
| 最大值 | 确定集合中的最大值。 | 不适用。 |
Enumerable.Max Queryable.Max |
| 最小值 | 确定集合中的最小值。 | 不适用。 |
Enumerable.Min Queryable.Min |
| Sum | 对集合中的值求和。 | 不适用。 |
Enumerable.Sum Queryable.Sum |