zoukankan      html  css  js  c++  java
  • 组内Linq培训记录

    注: 由于该培训是在组内分享,先写成了Word,而word中的代码都以截图方式呈现了,而在博客园不能很方便的粘贴截图进来,所以我用插入代码的方式加进来,如果文中说“如下图”或“如下图代码”,那么就直接看下面的代码块就可以了。

    Linq基本用法

    1. 1.       前言:

    要说Linq,要先做一些相关内容的铺垫。请稍安勿躁,下面马上开始。

     

    1. 2.       集合和IEnumerable

    集合包括数组、字典、列表等类型,这些类型都实现了IEnumerable(可枚举)接口。

    1. 3.       隐式类型和var关键字

    从.net 3.0开始,引入了隐式类型var,隐式类型的本地变量是强类型变量(就好像您已经声明该类型一样),但由编译器确定类型。 下面的两个声明在功能上是等效的:

    double num = 1.0;

    var num = 1.0;

    由于var关键字声明的变量的类型是由编译器决定的,编译器判断的方法是在声明时,根据变量被赋值的类型来决定变量类型, 所以要求在声明时就进行赋值,否则编译器无法确定变量的类型, 所以如下写法是无效的:

    var num;

             日常开发中,可以都用var来声明变量,据说这样性能更优。

    1. 4.       扩展方法

    扩展方法使您能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。 扩展方法是一种特殊的静态方法,但可以像扩展类型上的实例方法一样进行调用。 

    a)         如何实现扩展方法

    实现一个空的Cat类,并在该类外进行扩展,扩展一个Eat方法。扩展类CatExtend可以随便命名,但一定要是静态(Static)类,而且扩展的方法需要是静态方法,扩展方法的第一个参数的类型为(this关键字加要扩展的类)

     1 public class Cat 
     2     {
     3     }
     4 
     5     public static class CatExtend
     6     {
     7         public static void Eat(this Animal c, string foodName)
     8         {
     9             Console.WriteLine("Animal eat {0}", foodName);
    10         }
    11     }
    View Code

    调用该方法的代码为:

    1 var myCat = new Cat();
    2 myCat.Eat('fish');
    3 
    4 // 输出 Cat eat fish
    View Code

             我们也可以扩展现有的类型,如Int32:

    1 public static class Int32Extend
    2 {
    3     public static int Pow(this Int32 i, int power)
    4     {
    5 
    6         var pow = Math.Pow(i, power);
    7         int result = Int32.TryParse(pow.ToString(), out result) ? result : 0;    
    8     }   
    9 }
    View Code

            

    1. 5.       委托和Lambda表达式

    在说Lambda之前,需要先简单提一下委托

    a)         委托:

    委托是一种定义方法签名的类型,可以与具有兼容签名的任何方法关联。您可以通过委托调用方法。委托用于将方法作为参数传递给其他方法。事件处理程序就是通过委托调用的方法。你可以用委托创建一个自定义方法,并将这个方法作为参数传递给其他方法。 这类似于JS中的回调函数。

    b)         Lambda表达式:

    “Lambda 表达式”是一个匿名函数,它可以包含表达式和语句,并且可用于创建委托或表达式目录树类型。

    所有 Lambda 表达式都使用 Lambda 运算符 =>,该运算符读为“goes to”。该 Lambda 运算符的左边是输入参数(如果有),右边包含表达式或语句块。Lambda 表达式 x => x * x 读作“x goes to x times x”。可以将此表达式分配给委托类型,如下所示:

    delegate int del(int i);
    del myDelegate = x => x * x;
    int j = myDelegate(5); //j = 25
    其中的 x => x * x;  就是Lambda表达式。
     
    Lambda表达式的标准形式为:
                          (input parameters) => expression
     
    Input parameters为传入参数,当有多个时,用逗号分隔,可以不指定类型,编译器会自动判断,但也有些情况编译器无法自动判断,这是可以给参数指定类型。仅当传入参数个数为一个时,左边的括号可以忽略,否则必须写括号,如:
                          (x, y)=> x * y;
                          () => return 0;   // 当无传入参数时,也要写上括号。
     
    Expression为该匿名函数的处理逻辑, 当该函数是直接通过一个语句返回结果,可以像上面的代码那么写,但如果需要一些逻辑处理语句,那么,可以像下面这么写:

    (x, y) => { var i = x + 1; return i * y; }

    具体可查看http://msdn.microsoft.com/zh-cn/library/bb397687(v=vs.90).aspx

    c)         Func<>和Action<>

    Func和Action都是函数类型,即上述的所有Lambda表达式都可赋值给相应的函数类型,以便之后调用。如:

    1 Func<int, int> fn1 = (x,y) => { var i = x+1; return i * y; };
    2 Action<string> ac1 = (name) => {Console.WriteLine("Hello {0}.", name); };
    View Code

    Func和Action的区别在于,Func有一个返回值,而Action没有返回值。

    根据上述代码,可看出Func和Action后的尖括号中,有逗号分隔的各种类型,这些类型表示的意思为:

    l  Func: 最后一个类型为返回值的类型,之前的所有类型都是传入参数的类型,当只有一个类型时,为返回值的类型。

    l  Action:全部类型都是传入参数的类型,也可以用不带尖括号的形式来声明,此时没传入参数。

    Func和Action都能最多接受16个传入参数。

    1. 6.       Linq表达式

    Linq表达式接近于SQL的语法,书写起来比扩展方法具有更高的可读性,基本上熟悉SQL语法的程序员一看到Linq表达式,即使没用过,也能大概猜出语句的含义。这也是Linq的优势之一。

    当引用了System.Linq命名空间后,就可以对所有可枚举类型使用Linq的方法和特性。包括Array,List,DataTable,各类型数组的对象等等。其中对DataTable等对象使用时,需要用AsEnumerable方法先转换成可枚举类型。

    比较简单的Linq表达式:

    1 int[] numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 };
    2 var numQuery = 
    3     from num in numbers
    4     where ( num%2 ) == 0
    5     select num;
    6 
    7 // return 0,2,4,6
    View Code

    其中numbers是数据源。一般linq的查询结果的类型都用var。

    a)         和扩展方法的关系

    Linq表达式在编译器中编译后,都会先变成扩展方法的样子,即上述例子在编译后会先变成:

    Var numQuery = numbers.Where(num=>num%2==2).Select(num=> num);

    b)         常用关键字及用法

    以下大多数的关键字作用和SQL中的关键字或方法一一对应,作用一样。

                             i.              From、Select、Where

    Linq表达式都需要用到From关键字。

    var q = from num in numbers select num;

    其中的num是对numbers集合中的每个元素自定义的别名。

    1  var q = from i in intArray
    2             where i >100
    3             select i;
    View Code

                           ii.              Count、Max、Min、Average、Sum、First

    1 q=  from i in intArray
    2        select i;
    3 
    4 Console.WriteLine("There are {0} numbers in intArray ", q.Count());
    5 Console.WriteLine("The max number is : {0} ", q.Max());
    6 Console.WriteLine("The min number is : {0} ", q.Min());
    7 Console.WriteLine("The average number is : {0} ", q.Average());
    8 Console.WriteLine("The sum of all numbers is : {0} ", q.Sum());
    9 Console.WriteLine("The first number is : {0} ", q.First());
    View Code

                          iii.              Concat、Union、Distinct

    Concat为直接拼接2个同类型数组,并返回。

    Union为拼接拼接2个同类型数组,并过滤掉重复项,并返回结果。

    Distinct为过滤一个数组中的重复项并返回结果。

    示例,有如下数据源:

    1 var intArr1 = new int[] { 1, 2, 3 };
    2 var intArr2 = new int[] { 1, 2, 4 };
    3 var intArr3 = intArr1.Concat(intArr2);
    4 var intArr4 = intArr1.Union(intArr2);
    5 var intArr5 = intArr3.Distinct();
    View Code

    这么输出的话,结果如下:

     1 foreach(var i in intArr3)
     2 {
     3      Console.Write("{0},", i);   
     4 }
     5 
     6 foreach(var i in intArr4)
     7 {
     8      Console.Write("{0},", i);   
     9 }
    10 
    11 foreach(var i in intArr5)
    12 {
    13      Console.Write("{0},", i);   
    14 }
    15 
    16 
    17 // intArr3:  1,2,3,1,2,4
    18 // intArr4:  1,2,3,4
    19 // intArr5:  1,2,3,4
    View Code

                          iv.              Group、Group Join

    Group的作用和SQL中的GROUP BY一样,GROUP JOIN和SQL中的JOIN一样。

    示例: 假如有如下数据源:

     1 Person[] persons = new Person[]{
     2     new Person("Peter", sex.Male),
     3     new Person("Tom", sex.Male),
     4     new Person("Sue", sex.Female),
     5     new Person("Ken", sex.Male),
     6     new Person("Linda", sex.Female)
     7 };
     8 
     9 Sport[] sports = new Sport[]{
    10     new Sport(sex.Male, "Swim"),
    11     new Sport(sex.Male, "Tennis"),
    12     new Sport(sex.Female, "Draw")
    13 };
    View Code

    现在要按性别对persons数组进行group的话,可以这么写:

    1 var personQuery = from p in persons
    2                             group p by p.sex into g
    3                             select new { Sex = g.Key, Persons = g};
    View Code

    这里personQuery会得到两个集合,一个是性别为男的Person集合,一个是性别为女的Person集合。 Select new中的Sex,是性别, Persons是该性别的对象集合。

    如果这样输出:

    1 foreach(var g in personQuery)
    2 {
    3     Console.WriteLine("{0} are:", g.Sex);
    4     foreach(Person pp in g.Persons)
    5     {
    6         Console.Write("{0},", pp.name);
    7     }
    8     Console.WriteLine();
    9 }
    View Code

    可以得到以下结果:

    1 /*
    2 Male are:
    3 Peter,Tom,Ken
    4 Female are:
    5 Sue,Linda
    6 */
    View Code

                           v.              OrderBy、ThenBy

    Order by作用和SQL中一样,可指定升序和降序,linq表达式的orderby支持多字段排序。如下:

     1 var orderByQ = from p in persons
     2                         order by p.sex descending, p.name descending
     3                         select p;
     4 
     5 Console.WriteLine("The person after order by sex and name");
     6 foreach( var p in orderByQ)
     7 {
     8     Console.Wirte("{0}," p.name);
     9 }
    10 Console.WirteLine();
    View Code

    输出为:

    1 /*
    2 The person after order by sex and name
    3 Sue,Linda,Tom,Peter,Ken,
    4 
    5 */
    View Code

     注:这里之所以Female会排在Male之前,因为性别是枚举类型,这里性别的排序不是根据Female和Male的拼写进行排序,而是根据其对应的枚举值进行排序。 Male的枚举值是1,Female是2,所以降序时,Female排在Male之前。

    ThenBy主要用在扩展方法,上述查询如果要用扩展方法书写,应该这么写:

    var orderByQ = persons.OrderByDescending(p => p.sex).ThenByDescending(p => p.name);

    如果要多字段排序,要用ThenBy,否则只会按照最后一个OrderBy进行排序。

    扩展方法中,有OrderBy、OrderByDescending、ThenBy、ThenByDescending,分别对应了升序和降序。

                          vi.              ToArray、ToList

    这两个都属于扩展方法,可以将Linq查询结果转换成对应的类型或泛型。用起来非常简单,用上述的orderByQ的查询结果来转换,

    1 Person[] personArr = orderByQ.ToArray();
    2 List<Person> personList = orderByQ.ToList();
    View Code
  • 相关阅读:
    HDU 5585 Numbers
    HDU 3308 LCIS
    POJ 2991 Crane
    POJ 1436 Horizontally Visible Segments
    POJ 3667 Hotel
    HaiHongOJ 1003 God Wang
    【SDOI 2008】 递归数列
    5月19日省中提高组题解
    【HDU 1588】 Gauss Fibonacci
    【POJ 3233】Matrix Power Series
  • 原文地址:https://www.cnblogs.com/bee0060/p/3467979.html
Copyright © 2011-2022 走看看