Linq查询操做之排序操做

  在Linq中排序操做能够按照一个或多个关键字对序列进行排序。其中第一个排序关键字为主要关键字,第二个排序关键字为次要关键字。Linq排序操做共包含如下5个基本的操做。web

一、OrderBy操做,根据排序关键字对序列进行升序排序函数

二、OrderByDescending操做,根据排序关键字对序列进行降序排序测试

三、ThenBy操做,对次要关键字进行升序排序this

四、ThenByDescending操做,对次要关键字进行降序排序spa

五、Reverse操做,将序列中的元素进行反转3d

  那么下面咱们就逐一来分析一下每一个排序操做。code

OrderBy操做blog

  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         }

运行结果:

能够看出,只是把序列的元素反转了,并不会进行升序或者降序排序。

咱们来看看内部实现,内部实现其实很简单:

就是对序列反向输出。

相关文章
相关标签/搜索