程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> LINQ學習筆記:排序Ordering

LINQ學習筆記:排序Ordering

編輯:關於.NET

排序Ordering

主要方法:

OrderBy, ThenBy: 正序排列輸入序列, SQL對應語法為ORDER BY

OrderByDescending, ThenByDescending: 倒序排列輸入序列, SQL對應語法為ORDER BY … DESC

Reverse: 反轉輸入序列, 無SQL對應語法

排序操作符返回不同順序但與輸入序列相同的元素

OrderBy, OrderByDescending參數:

輸入序列: IEnumerable

主鍵選擇器: TSource => TKey

返回類型是IOrderedEnumerable

ThenBy, ThenByDescending參數:

輸入序列: IOrderedEnumerable

主鍵選擇器:TSource => TKey

簡要介紹:

OrderBy返回輸入序列的一個排序版本, 其使用keySelector表達式作比較. 以下的例子返回了按字母排序的名字列表:

   1: IEnumerable<string> query = names.OrderBy(n => n);

 

此例子則是按名字長度排序:

   1: IEnumerable<string> query = names.OrderBy (n => n.Length);

 

如果元素具有相同的排序鍵那麼它們的順序可能是不確定的 – 除非你增加一個ThenBy操作符:

   1: string[] names = {“James”, “Jack”, “Todd”, “David”, “Kobe”};
   2:  
   3: IEnumerable<string> query = names.OrderBy (n => n.Length)
   4:  
   5: .ThenBy (n => n);
   6:  
   7: //{Jack,Todd,Kobe,James,David}

 

ThenBy只會重新排列那些擁有同樣排序鍵的元素.你可以串聯任意多個ThenBy操作符,如下示例:

   1: IEnumerable<string> query = names.OrderBy (s => s.Length)
   2:  
   3: ThenBy (s => s[1]).ThenBy (s => s[0]);

 

先按名字長度排序, 再按第2個字符排序, 最後再按第1個字符排序, 其對應的復合查詢為:

   1: IEnumerable<string> query = from s in names
   2:  
   3: rderby s.Length, s[1], s[0]
   4:  
   5: elect s;

 

LINQ另外也提供了OrderByDescending和ThenByDescending操作符,生成一個倒序的結果集,以下的LINQ to SQL的示例表示按照價格倒序再按描述的字母順序排列:

   1: dataContext.Purchases.OrderByDescending(p => p.Price)
   2:  
   3: .ThenBy (p =>p.Description);

 

復合語法為:

   1: from p in dataContext.Purchases
   2:  
   3: orderby p.Price descending, p.Description
   4:  
   5: select p;

 

Comparers和Collations

在本地查詢中, 鍵選擇器本身會通過他們默認的IComparable實現來決定排序算法. 我們可以通過提供一個IComparer對象來覆蓋默認的排序算法, 以下示例表示要執行一個大小寫無關的排序:

   1: names.OrderBy (n => n, StringComparer.CurrentCultureIgnoreCase);

 

在復合查詢中不支持傳遞Comparer,同樣LINQ to SQL當中也不支持. 在LINQ to SQL當中, 比較算法是由對應列的collation決定的. 如果collation是大小寫敏感的,你可以通過在鍵選擇器中調用ToUpper來完成非大小寫敏感的排序:

   1: from p in dataContext.Purchases
   2:  
   3: orderby p.Description. ToUpper()
   4:  
   5: select p;

 

IOrderedEnumerable與IOrderedQueryable

排序操作符返回了特殊的IEnumerable子類, 如果是Enumerable那麼則對應是IOrderedEnumerable,如果是Queryable,則返回的是IOrderedQueryable類. 這些子類型允許使用一個後來的ThenBy操作符繼續提煉而不是代替之前的排列順序.

這些子類型定義的成員並非公開暴露的, 因此他們看起來像是原始序列.

但實際上他們是不同類型, 當我們漸進創建查詢的時候就可以發現:

   1: IOrderedEnumerable<string> query1 =
   2:  
   3: ames.OrderBy (s => s.Length);
   4:  
   5: OrderedEnumerable<string> query2 =
   6:  
   7: uery1.ThenBy (s => s);

 

如果我們使用IEnumerable帶來query1現有的生命,那麼第二行將無法編譯—ThenBy需要一個IOrderedEnumerable類型的輸入.當然, 使用var可以免去這個擔心:

   1: var query1 = names.OrderBy (s =>s.Length);
   2:  
   3: var query2 = query1. ThenBy (s => s);

 

然而, 使用隱式類型可能也會有一些問題, 如下:

   1: var query = names.OrderBy (s =>s.Length);
   2:  
   3: query = query.Where (n =>n.Length > 3); //錯誤,無法編譯

 

OrderBy輸出的序列類型是IOrderedEnumerable, 然後對於下一行的Where操作來說它的輸出類型是IEnumerable因此無法再次賦值給query,解決的辦法是在OrderBy之後顯式調用AsEnumerable():

   1: var query = names.OrderBy (s =>s.Length).AsEnumerable();
   2:  
   3: query =query.Where (n => n.Length > 3); // OK

 

對於解釋性查詢, 與之對應的是調用AsQueryable().待續!

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved