Linq查詢操作之排序操作


  在Linq中排序操作可以按照一個或多個關鍵字對序列進行排序。其中第一個排序關鍵字為主要關鍵字,第二個排序關鍵字為次要關鍵字。Linq排序操作共包含以下5個基本的操作。

1、OrderBy操作,根據排序關鍵字對序列進行升序排序

2、OrderByDescending操作,根據排序關鍵字對序列進行降序排序

3、ThenBy操作,對次要關鍵字進行升序排序

4、ThenByDescending操作,對次要關鍵字進行降序排序

5、Reverse操作,將序列中的元素進行反轉

  那么下面我們就逐一來分析一下每個排序操作。

OrderBy操作

  OrderBy操作是按照主關鍵字對序列進行升序排序的操作。Enumerable類的OrderBy()原型如下:

1public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
    return new OrderedEnumerable<TSource, TKey>(source, keySelector, null, false);
}

 
2public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
{
    return new OrderedEnumerable<TSource, TKey>(source, keySelector, comparer, false);
}

 

 


 

其中source表示數據源,keySelector表示獲取排序的關鍵字的函數,comparer參數表示排序時的比較函數。TSource表示數據源的類型,TKey表示排序關鍵字的類型。下面我們用兩種方式來比較排序,第一種按照前面講的查詢表達式來排序,第二種用現在的排序操作來排序,其實結果都是一樣的。

private void OrderByQuery()
        {
            int[] ints = new int[] { 1, 3, 5, 4, 7, 6, 8 };

            //使用查詢表達式來排序

            Response.Write("--------------使用查詢表達式來排序---------</br>");
            var values = from v in ints

                         orderby v

                         select v;

            foreach (var item in values)
            {

                Response.Write(item+"</br>");
            }
             //使用排序操作來排序

            Response.Write("--------------使用排序操作來排序---------</br>");

            var result = ints.OrderBy(x => x);

            foreach (var re in result)
            {

                Response.Write(re + "</br>");
            }

        }

看看運行結果:

我們看到和我們預想的是一樣的。那么大家可能有些疑問,為什么OrderBy是升序排序呢?

我們來從源碼解析一下:

我們看到OrderBy里面最終調用了一個函數OrderedEnumerable,那么我們再來看看這個OrderedEnumerable函數:

看到這個函數有一個參數descending,我們OrderBy方法給這個參數傳了false,那么就表示非降序排序,就是升序排序。可想而知,OrderByDescending操作,給這個參數傳值應該是true。

第二個原型里面有個comparer參數,那么我們來看看怎么用:既然是IComparer接口類型的參數,那么我們就定義一個實現了Icomparer接口的類型:

 1 private void OrderByQuery()
 2         {
 3             int[] ints = new int[] { 1, 3, 5, 4, 7, 6, 8 };
 4 
 5 
 6             var result = ints.OrderBy(x => x,new CompareIntegers());
 7 
 8             foreach (var re in result)
 9             {
10 
11                 Response.Write(re + "</br>");
12             }
13 
14         }
15 
16         public class CompareIntegers : IComparer<int>
17         {
18             public int Compare(int i1, int i2)
19             {
20                 return -1*(i1 - i2);
21             }
22         }

我們看到,我們定義的CompareIntegers類的比較參數是,該元素取反,所以排序結果應該就成了降序排序了。我們看看測試結果:

嗯和我們預想的一樣,這個comparer函數就是我們自定義的比較方式。

OrderByDescending操作

  OrderByDescending和我們上面的OrderBy操作相似,最終都是調用OrderedEnumerable只是傳入的descending參數的值不同。看看OrderByDescending的原型:

    public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector);

    public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer);

也有兩個原型,跟OrderBy的原型一模一樣,只是最終調用OrderedEnumerable方法的傳入參數不同。

我們看到這個傳入的是true,表示降序排列。所以我個人覺得這兩個操作可以合並,然后多一個參數而已。

同樣寫個例子測試一下:

 1  private void OrderByDescendingQuery()
 2         {
 3             int[] ints = new int[] { 1, 3, 5, 4, 7, 6, 8 };
 4 
 5             //使用查詢表達式來排序
 6 
 7             Response.Write("--------------使用查詢表達式來排序---------</br>");
 8             var values = from v in ints
 9 
10                          orderby v descending
11 
12                          select v;
13 
14             foreach (var item in values)
15             {
16 
17                 Response.Write(item+"</br>");
18             }
19          //使用排序操作來排序
20 
21             Response.Write("--------------使用排序操作來排序---------</br>");
22 
23             var result = ints.OrderByDescending(x => x);
24 
25             foreach (var re in result)
26             {
27 
28                 Response.Write(re + "</br>");
29             }
30 
31         }

看看測試結果:

嗯結果和預想的一樣。

ThenBy操作

  上面兩個排序都是按照主關鍵字來排序的,下面呢我們就看看什么是按照次要關鍵字排序。ThenBy 和OrderBy一樣是按照升序排序的。來看看原型:

    public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey>(this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector);
    public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey>(this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer);

原型和OrderBy一樣。但是ThenBy必須要和OrderBy配合使用。就是 必須要先有OrderBy排序,然后再用ThenBy排序。不能夠直接用ThenBy排序。
同樣我們寫個例子一看便知。這個例子呢我們每個序列的每個元素至少要有兩個字段,一個做主關鍵字,一個做次要關鍵字。我們還是用前面將的UserBaseInfo來創建例子,用ID做主關鍵字,username做次要關鍵字。

 1 private void ThenByQuery()
 2         {
 3             IList<UserBaseInfo> users = new List<UserBaseInfo>();
 4 
 5             for (int i = 1; i < 10; i++)
 6             {
 7                 users.Add(new UserBaseInfo(i, "user0" + i.ToString(), "user0" + i.ToString() + "@web.com"));
 8             }
 9 
10             var values = users.OrderBy(u => u.ID).ThenBy(x => x.UserName);
11 
12             foreach (var u in values)
13             {
14                 Response.Write("ID:" + u.ID + "</br>" + "username:" + u.UserName + "</br>");
15             }
16 
17 
18         }

看看結果:

ThenByDescending操作

  這個是ThenBy的降序排序方式,和前面的用法實質是一樣的,我就不詳細講解了,大家可以自己研究一下。

Reverse操作

  下面我們就來看看Reverse這個排序。這個排序呢可以說也不算是排序,因為我們知道排序無非就是升序,或者降序。這個其實就是將一個序列進行反轉,里面的值如果本來沒有順序,執行這個操作之后,也不會變得有序,只是序列的元素反轉。

看看reverse的原型:

public static IEnumerable<TSource> Reverse<TSource>(this IEnumerable<TSource> source);

測試樣例:

 1 private void ReverseQuery()
 2         {
 3             IList<UserBaseInfo> users = new List<UserBaseInfo>();
 4 
 5             for (int i = 1; i < 10; i++)
 6             {
 7                 users.Add(new UserBaseInfo(i, "user0" + i.ToString(), "user0" + i.ToString() + "@web.com"));
 8             }
 9 
10             var values = users.Reverse();
11 
12             foreach (var u in values)
13             {
14                 Response.Write("ID:" + u.ID + "</br>" + "username:" + u.UserName + "</br>");
15             }
16 
17 
18         }

運行結果:

看確實是反轉了。

  再看一個本來無序的例子。

 1 private void ReverseQuery()
 2         {
 3             int[] ints = new int[] { 1, 3, 5, 4, 7, 6, 8 };
 4 
 5 
 6             var result = ints.Reverse();
 7 
 8             foreach (var re in result)
 9             {
10 
11                 Response.Write(re + "</br>");
12             }
13 
14         }

運行結果:

可以看出,只是把序列的元素反轉了,並不會進行升序或者降序排序。

我們來看看內部實現,內部實現其實很簡單:

就是對序列反向輸出。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM