C#3.0新增功能09 LINQ 標準查詢運算符 04 運算

本篇主要介紹標準查詢運算符的經常使用運算功能。html

01 對數據排序

排序操做基於一個或多個屬性對序列的元素進行排序。 第一個排序條件對元素執行主要排序。 經過指定第二個排序條件,您能夠對每一個主要排序組內的元素進行排序。sql

下圖展現了對一系列字符執行按字母順序排序操做的結果。數據庫

展現按字母順序排序操做的圖。

下節列出了對數據進行排序的標準查詢運算符方法。express

方法

方法名 說明 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 子句按字符串的第一個字母對字符串進行降序排序。api

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  
*/

次要排序示例

次要升序排序

下面的示例演示如何在 LINQ 查詢中使用 orderby 子句對數組中的字符串執行主要和次要排序。 首先按字符串長度,其次按字符串的第一個字母,對字符串進行升序排序。數組

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  
*/

次要降序排序

下面的示例演示如何在 LINQ 查詢中使用 orderby descending 子句按升序執行主要排序,按降序執行次要排序。 首先按字符串長度,其次按字符串的第一個字母,對字符串進行排序。app

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  
*/
02 Set(集)運算

LINQ 中的集運算是指根據相同或不一樣集合(或集)中是否存在等效元素來生成結果集的查詢運算。框架

下節列出了執行集運算的標準查詢運算符方法。ide

方法

方法名 說明 C# 查詢表達式語法 詳細信息
Distinct 刪除集合中的重複值。 不適用。 Enumerable.Distinct

Queryable.Distinct
Except 返回差集,差集指位於一個集合但不位於另外一個集合的元素。 不適用。 Enumerable.Except

Queryable.Except
相交 返回交集,交集指同時出如今兩個集合中的元素。 不適用。 Enumerable.Intersect

Queryable.Intersect
聯合 返回並集,並集指位於兩個集合中任一集合的惟一的元素。 不適用。 Enumerable.Union

Queryable.Union

 

比較集運算

Distinct

下圖演示字符序列上 Enumerable.Distinct 方法的行爲。 返回的序列包含輸入序列的惟一元素。

顯示 Distinct() 的行爲的圖。

Except

下圖演示 Enumerable.Except 的行爲。 返回的序列只包含位於第一個輸入序列但不位於第二個輸入序列的元素。

顯示 Except() 操做的圖形

相交

下圖演示 Enumerable.Intersect 的行爲。 返回的序列包含兩個輸入序列共有的元素。

顯示兩個序列的交集的圖。

聯合

下圖演示對兩個字符序列執行的聯合操做。 返回的序列包含兩個輸入序列的惟一元素。

顯示兩個序列的並集的圖。

03 篩選數據

篩選是指將結果集限制爲僅包含知足指定條件的元素的操做。 它也稱爲選定內容。

下圖演示了對字符序列進行篩選的結果。 篩選操做的謂詞指定字符必須爲「A」。

顯示 LINQ 篩選操做的圖表

下面一節列出了執行所選內容的標準查詢運算符方法。

方法

方法名 說明 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  
*/
04 限定符運算

限定符運算返回一個 Boolean 值,該值指示序列中是否有一些元素知足條件或是否全部元素都知足條件。

下圖描述了兩個不一樣源序列上的兩個不一樣限定符運算。 第一個運算詢問是否有一個或多個元素爲字符「A」,結果爲 true。 第二個運算詢問是否全部元素都爲字符「A」,結果爲 true

LINQ 限定符運算

下節列出了執行限定符運算的標準查詢運算符方法。

方法

方法名 說明 C# 查詢表達式語法 詳細信息
所有 肯定是否序列中的全部元素都知足條件。 不適用。 Enumerable.All

Queryable.All
任意 肯定序列中是否有元素知足條件。 不適用。 Enumerable.Any

Queryable.Any
包含 肯定序列是否包含指定的元素。 不適用。 Enumerable.Contains

Queryable.Contains
 
05 投影運算

投影是指將對象轉換爲一種新形式的操做,該形式一般只包含那些將隨後使用的屬性。 經過使用投影,您能夠構造從每一個對象生成的新類型。 能夠投影屬性,並對該屬性執行數學函數。 還能夠在不更改原始對象的狀況下投影該對象。

下面一節列出了執行投影的標準查詢運算符方法。

方法

方法名 說明 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

Select() 和 SelectMany() 的工做都是依據源值生成一個或多個結果值。 Select() 爲每一個源值生成一個結果值。 所以,整體結果是一個與源集合具備相同元素數目的集合。 與之相反,SelectMany() 生成單個整體結果,其中包含來自每一個源值的串聯子集合。 做爲參數傳遞到 SelectMany() 的轉換函數必須爲每一個源值返回一個可枚舉值序列。 而後,SelectMany() 串聯這些可枚舉序列,以建立一個大的序列。

下面兩個插圖演示了這兩個方法的操做之間的概念性區別。 在每種狀況下,假定選擇器(轉換)函數從每一個源值中選擇一個由花卉數據組成的數組。

下圖描述 Select() 如何返回一個與源集合具備相同元素數目的集合。

顯示 Select() 的操做的圖

下圖描述 SelectMany() 如何將中間數組序列串聯爲一個最終結果值,其中包含每一箇中間數組中的每一個值。

顯示 SelectMany() 的操做的圖。

代碼示例

下面的示例比較 Select() 和 SelectMany() 的行爲。 代碼經過從源集合的每一個花卉名稱列表中提取前兩項來建立一個「花束」。 此示例中,transform 函數 Select<TSource,TResult>(IEnumerable<TSource>, Func<TSource,TResult>) 使用的「單值」自己便是值的集合。 這須要額外的 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 }
06 數據分區

LINQ 中的分區是指將輸入序列劃分爲兩個部分的操做,無需從新排列元素,而後返回其中一個部分。

下圖顯示對字符序列進行三種不一樣的分區操做的結果。 第一個操做返回序列中的前三個元素。 第二個操做跳過前三個元素,返回剩餘元素。 第三個操做跳過序列中的前兩個元素,返回接下來的三個元素。

顯示三個 LINQ 分區操做的圖示。

下面一節列出了對序列進行分區的標準查詢運算符方法。

運算符

運算符名稱 說明 C# 查詢表達式語法 詳細信息
Skip 跳過序列中指定位置以前的元素。 不適用。 Enumerable.Skip

Queryable.Skip
SkipWhile 基於謂詞函數跳過元素,直到元素不符合條件。 不適用。 Enumerable.SkipWhile

Queryable.SkipWhile
Take 獲取序列中指定位置以前的元素。 不適用。 Enumerable.Take

Queryable.Take
TakeWhile 基於謂詞函數獲取元素,直到元素不符合條件。 不適用。 Enumerable.TakeWhile

Queryable.TakeWhile
 
07 聯接運算

聯接兩個數據源就是將一個數據源中的對象與另外一個數據源中具備相同公共屬性的對象相關聯。

當查詢所面向的數據源相互之間具備沒法直接領會的關係時,聯接就成爲一項重要的運算。在面向對象的編程中,這可能意味着在未建模對象之間進行關聯,例如對單向關係進行反向推理。 下面是單向關係的一個示例:Customer 類有一個類型爲 City 的屬性,但 City 類沒有做爲 Customer 對象集合的屬性。 若是你具備一個 City 對象列表,而且要查找每一個城市中的全部客戶,則可使用聯接運算完成此項查找。

LINQ 框架中提供的 join 方法包括 Join 和 GroupJoin。 這些方法執行同等聯接,即根據 2 個數據源的鍵是否相等來匹配這 2 個數據源的聯接。 (與此相較,Transact-SQL 支持除「等於」以外的聯接運算符,例如「小於」運算符。)用關係數據庫術語表達,就是說 Join 實現了內部聯接,這種聯接只返回那些在另外一個數據集中具備匹配項的對象。 GroupJoin 方法在關係數據庫術語中沒有直接等效項,但實現了內部聯接和左外部聯接的超集。 左外部聯接是指返回第一個(左側)數據源的每一個元素的聯接,即便其餘數據源中沒有關聯元素。

下圖顯示了一個概念性視圖,其中包含兩個集合以及這兩個集合中的包含在內部聯接或左外部聯接中的元素。

顯示內部/外部的兩個重疊圓圈。

方法

方法名 說明 C# 查詢表達式語法 詳細信息
聯接 根據鍵選擇器函數聯接兩個序列並提取值對。 join … in … on … equals … Enumerable.Join

Queryable.Join
GroupJoin 根據鍵選擇器函數聯接兩個序列,並對每一個元素的結果匹配項進行分組。 join … in … on … equals … into … Enumerable.GroupJoin

Queryable.GroupJoin

其餘技術請參閱

 
08 數據分組

分組是指將數據分到不一樣的組,使每組中的元素擁有公共的屬性。

下圖演示了對字符序列進行分組的結果。 每一個組的鍵是字符。

關係圖顯示 LINQ 分組操做。

下一節列出了對數據元素進行分組的標準查詢運算符方法。

方法

方法名 說明 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  
*/

其餘技術請參閱

 

09 生成運算

生成是指建立新的值序列。

下面一節列出了執行生成的標準查詢運算符方法。

方法

方法名 說明 C# 查詢表達式語法 詳細信息
DefaultIfEmpty 用默認值單一實例集合替換空集合。 不適用。 Enumerable.DefaultIfEmpty

Queryable.DefaultIfEmpty
返回一個空集合。 不適用。 Enumerable.Empty
範圍 生成包含數字序列的集合。 不適用。 Enumerable.Range
Repeat 生成包含一個重複值的集合。 不適用。 Enumerable.Repeat
 
10 相等運算

兩個序列,其相應元素相等且具備被視爲相等的相同數量的元素。

方法

方法名 說明 C# 查詢表達式語法 更多信息
SequenceEqual 經過以成對方式比較元素肯定兩個序列是否相等。 不適用。 Enumerable.SequenceEqual

Queryable.SequenceEqual
 
11 元素運算

元素運算從序列中返回惟1、特定的元素。

下節列出了執行元素運算的標準查詢運算符方法。

方法

方法名 說明 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
 
12 數據類型轉換

轉換方法可更改輸入對象的類型。

LINQ 查詢中的轉換運算可用於各類應用程序。 如下是一些示例:

方法

下表列出了執行數據類型轉換的標準查詢運算符方法。

本表中名稱以「As」開頭的轉換方法可更改源集合的靜態類型,但不對其進行枚舉。 名稱以「To」開頭的方法可枚舉源集合,並將項放入相應的集合類型。

方法名 說明 C# 查詢表達式語法 詳細信息
AsEnumerable 返回類型化爲 IEnumerable<T> 的輸入。 不適用。 Enumerable.AsEnumerable
AsQueryable 將(泛型)IEnumerable 轉換爲(泛型)IQueryable 不適用。 Queryable.AsQueryable
Cast 將集合中的元素轉換爲指定類型。 使用顯式類型化的範圍變量。 例如:

from string str in words
Enumerable.Cast

Queryable.Cast
OfType 根據其轉換爲指定類型的能力篩選值。 不適用。 Enumerable.OfType

Queryable.OfType
ToArray 將集合轉換爲數組。 此方法強制執行查詢。 不適用。 Enumerable.ToArray
ToDictionary 根據鍵選擇器函數將元素放入 Dictionary<TKey,TValue>。 此方法強制執行查詢。 不適用。 Enumerable.ToDictionary
ToList 將集合轉換爲 List<T>。 此方法強制執行查詢。 不適用。 Enumerable.ToList
ToLookup 根據鍵選擇器函數將元素放入 Lookup<TKey,TElement>(一對多字典)。 此方法強制執行查詢。 不適用。 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 }
13 串聯運算

串聯是指將一個序列附加到另外一個序列的操做。

下圖描繪了兩個字符序列的串聯操做。

圖形顯示兩個序列的串聯。

下面一節列出了執行串聯的標準查詢運算符方法。

方法

方法名 說明 C# 查詢表達式語法 詳細信息
Concat 鏈接兩個序列以組成一個序列。 不適用。 Enumerable.Concat

Queryable.Concat
 
14 聚合運算

聚合運算從值的集合中計算出單個值。 例如,從一個月累計的每日溫度值計算出日平均溫度值就是一個聚合運算。

下圖顯示對數字序列進行兩種不一樣聚合操做所得結果。 第一個操做累加數字。 第二個操做返回序列中的最大值。

顯示 LINQ 聚合運算的插圖。

下節列出了執行聚合運算的標準查詢運算符方法。

方法

方法名 說明 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
 
相關文章
相關標籤/搜索