Ordering方法實現(xiàn)Linq排序
Linq排序方法有多種,本文只介紹Linq排序Ordering方法,要想輕輕松松的學習Linq排序是很容易實現(xiàn)的,但是要仔細讀此文章哦!
主要方法:
OrderBy, ThenBy: 正序排列輸入序列, SQL對應語法為ORDER BY
OrderByDescending, ThenByDescending: 倒序排列輸入序列, SQL對應語法為ORDER BY … DESC
Reverse: 反轉(zhuǎn)輸入序列, 無SQL對應語法
Linq排序操作符返回不同順序但與輸入序列相同的元素
OrderBy, OrderByDescending參數(shù):
輸入序列: IEnumerable
主鍵選擇器: TSource => TKey
返回類型是IOrderedEnumerable
ThenBy, ThenByDescending參數(shù):
輸入序列: IOrderedEnumerable
主鍵選擇器:TSource => TKey
簡要介紹:
OrderBy返回輸入序列的一個排序版本, 其使用keySelector表達式作比較. 以下的例子返回了按字母排序的名字列表:
- IEnumerable<string> query = names.OrderBy(n => n);
此例子則是按名字長度進行Linq排序:
- IEnumerable<string> query = names.OrderBy (n => n.Length);
如果元素具有相同的排序鍵那么它們的順序可能是不確定的 – 除非你增加一個ThenBy操作符:
- string[] names =
- {“James”, “Jack”, “Todd”, “David”, “Kobe”};
- IEnumerable<string> query = names.OrderBy (n => n.Length).ThenBy (n => n);
- //{Jack,Todd,Kobe,James,David}
ThenBy只會重新排列那些擁有同樣排序鍵的元素.你可以串聯(lián)任意多個ThenBy操作符,如下示例:
- IEnumerable<string> query = names.OrderBy (s => s.Length)
- ThenBy (s => s[1]).ThenBy (s => s[0]);
先按名字長度排序, 再按第2個字符排序, 最后再按第1個字符排序, 其對應的復合查詢?yōu)?
- IEnumerable<string> query = from s in names
- rderby s.Length, s[1], s[0] 4: 5: elect s;
Linq排序另外也提供了OrderByDescending和ThenByDescending操作符,生成一個倒序的結(jié)果集,以下的Linq to SQL的示例表示按照價格倒序再按描述的字母順序排列:
- dataContext.Purchases.OrderByDescending
- p => p.Price) .ThenBy (p =>p.Description);
復合語法為:
- from p in dataContext.Purchases
- orderby p.Price descending, p.Description
- select p;
Comparers和Collations
在本地查詢中, 鍵選擇器本身會通過他們默認的IComparable實現(xiàn)來決定Linq排序算法. 我們可以通過提供一個IComparer對象來覆蓋默認的排序算法, 以下示例表示要執(zhí)行一個大小寫無關(guān)的排序:
- names.OrderBy (n => n, StringComparer.CurrentCultureIgnoreCase);
在復合查詢中不支持傳遞Comparer,同樣Linq to SQL當中也不支持. 在Linq to SQL當中, 比較算法是由對應列的collation決定的. 如果collation是大小寫敏感的,你可以通過在鍵選擇器中調(diào)用ToUpper來完成非大小寫敏感的Linq排序:
- from p in dataContext.Purchases
- orderby p.Description. ToUpper()
- select p;
IOrderedEnumerable與IOrderedQueryable
排序操作符返回了特殊的IEnumerable子類, 如果是Enumerable那么則對應是IOrderedEnumerable,如果是Queryable,則返回的是IOrderedQueryable類. 這些子類型允許使用一個后來的ThenBy操作符繼續(xù)提煉而不是代替之前的排列順序.
這些子類型定義的成員并非公開暴露的, 因此他們看起來像是原始序列.
但實際上他們是不同類型, 當我們漸進創(chuàng)建查詢的時候就可以發(fā)現(xiàn):
- IOrderedEnumerable<string> query1 = ames.OrderBy (s => s.Length);
- OrderedEnumerable<string> query2 =uery1.ThenBy (s => s);
如果我們使用IEnumerable帶來query1現(xiàn)有的生命,那么第二行將無法編譯—ThenBy需要一個IOrderedEnumerable類型的輸入.當然, 使用var可以免去這個擔心:
- var query1 = names.OrderBy (s =>s.Length);
- var query2 = query1. ThenBy (s => s);
然而, 使用隱式類型可能也會有一些問題, 如下:
- var query = names.OrderBy (s =>s.Length);
- query = query.Where (n =>n.Length > 3); //錯誤,無法編譯
OrderBy輸出的序列類型是IOrderedEnumerable, 然后對于下一行的Where操作來說它的輸出類型是IEnumerable因此無法再次賦值給query,解決的辦法是在OrderBy之后顯式調(diào)用AsEnumerable():
- var query = names.OrderBy (s =>s.Length).AsEnumerable();
- query =query.Where (n => n.Length > 3); // OK
對于解釋性查詢, 與之對應的是調(diào)用AsQueryable()。
以上就是對Linq排序方法的簡單介紹。
【編輯推薦】