组内Linq培训记录
注: 由于该培训是在组内分享,先写成了Word,而word中的代码都以截图方式呈现了,而在博客园不能很方便的粘贴截图进来,所以我用插入代码的方式加进来,如果文中说“如下图”或“如下图代码”,那么就直接看下面的代码块就可以了。
Linq基本用法
- 1. 前言:
要说Linq,要先做一些相关内容的铺垫。请稍安勿躁,下面马上开始。
- 2. 集合和IEnumerable
集合包括数组、字典、列表等类型,这些类型都实现了IEnumerable(可枚举)接口。
- 3. 隐式类型和var关键字
从.net 3.0开始,引入了隐式类型var,隐式类型的本地变量是强类型变量(就好像您已经声明该类型一样),但由编译器确定类型。 下面的两个声明在功能上是等效的:
double num = 1.0;
var num = 1.0;
由于var关键字声明的变量的类型是由编译器决定的,编译器判断的方法是在声明时,根据变量被赋值的类型来决定变量类型, 所以要求在声明时就进行赋值,否则编译器无法确定变量的类型, 所以如下写法是无效的:
var num;
日常开发中,可以都用var来声明变量,据说这样性能更优。
- 4. 扩展方法
扩展方法使您能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。 扩展方法是一种特殊的静态方法,但可以像扩展类型上的实例方法一样进行调用。
a) 如何实现扩展方法
实现一个空的Cat类,并在该类外进行扩展,扩展一个Eat方法。扩展类CatExtend可以随便命名,但一定要是静态(Static)类,而且扩展的方法需要是静态方法,扩展方法的第一个参数的类型为(this关键字加要扩展的类)
public class Cat
{
} public static class CatExtend
{
public static void Eat(this Animal c, string foodName)
{
Console.WriteLine("Animal eat {0}", foodName);
}
}
调用该方法的代码为:
var myCat = new Cat();
myCat.Eat('fish'); // 输出 Cat eat fish
我们也可以扩展现有的类型,如Int32:
public static class Int32Extend
{
public static int Pow(this Int32 i, int power)
{ var pow = Math.Pow(i, power);
int result = Int32.TryParse(pow.ToString(), out result) ? result : ;
}
}
- 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表达式都可赋值给相应的函数类型,以便之后调用。如:
Func<int, int> fn1 = (x,y) => { var i = x+; return i * y; };
Action<string> ac1 = (name) => {Console.WriteLine("Hello {0}.", name); };
Func和Action的区别在于,Func有一个返回值,而Action没有返回值。
根据上述代码,可看出Func和Action后的尖括号中,有逗号分隔的各种类型,这些类型表示的意思为:
l Func: 最后一个类型为返回值的类型,之前的所有类型都是传入参数的类型,当只有一个类型时,为返回值的类型。
l Action:全部类型都是传入参数的类型,也可以用不带尖括号的形式来声明,此时没传入参数。
Func和Action都能最多接受16个传入参数。
- 6. Linq表达式
Linq表达式接近于SQL的语法,书写起来比扩展方法具有更高的可读性,基本上熟悉SQL语法的程序员一看到Linq表达式,即使没用过,也能大概猜出语句的含义。这也是Linq的优势之一。
当引用了System.Linq命名空间后,就可以对所有可枚举类型使用Linq的方法和特性。包括Array,List,DataTable,各类型数组的对象等等。其中对DataTable等对象使用时,需要用AsEnumerable方法先转换成可枚举类型。
比较简单的Linq表达式:
int[] numbers = new int[] { , , , , , , };
var numQuery =
from num in numbers
where ( num% ) ==
select num;
// return 0,2,4,6
其中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集合中的每个元素自定义的别名。
var q = from i in intArray
where i >
select i;
ii. Count、Max、Min、Average、Sum、First
q= from i in intArray
select i; Console.WriteLine("There are {0} numbers in intArray ", q.Count());
Console.WriteLine("The max number is : {0} ", q.Max());
Console.WriteLine("The min number is : {0} ", q.Min());
Console.WriteLine("The average number is : {0} ", q.Average());
Console.WriteLine("The sum of all numbers is : {0} ", q.Sum());
Console.WriteLine("The first number is : {0} ", q.First());
iii. Concat、Union、Distinct
Concat为直接拼接2个同类型数组,并返回。
Union为拼接拼接2个同类型数组,并过滤掉重复项,并返回结果。
Distinct为过滤一个数组中的重复项并返回结果。
示例,有如下数据源:
var intArr1 = new int[] { , , };
var intArr2 = new int[] { , , };
var intArr3 = intArr1.Concat(intArr2);
var intArr4 = intArr1.Union(intArr2);
var intArr5 = intArr3.Distinct();
这么输出的话,结果如下:
foreach(var i in intArr3)
{
Console.Write("{0},", i);
} foreach(var i in intArr4)
{
Console.Write("{0},", i);
} foreach(var i in intArr5)
{
Console.Write("{0},", i);
} // intArr3: 1,2,3,1,2,4
// intArr4: 1,2,3,4
// intArr5: 1,2,3,4
iv. Group、Group Join
Group的作用和SQL中的GROUP BY一样,GROUP JOIN和SQL中的JOIN一样。
示例: 假如有如下数据源:
Person[] persons = new Person[]{
new Person("Peter", sex.Male),
new Person("Tom", sex.Male),
new Person("Sue", sex.Female),
new Person("Ken", sex.Male),
new Person("Linda", sex.Female)
};
Sport[] sports = new Sport[]{
new Sport(sex.Male, "Swim"),
new Sport(sex.Male, "Tennis"),
new Sport(sex.Female, "Draw")
};
现在要按性别对persons数组进行group的话,可以这么写:
var personQuery = from p in persons
group p by p.sex into g
select new { Sex = g.Key, Persons = g};
这里personQuery会得到两个集合,一个是性别为男的Person集合,一个是性别为女的Person集合。 Select new中的Sex,是性别, Persons是该性别的对象集合。
如果这样输出:
foreach(var g in personQuery)
{
Console.WriteLine("{0} are:", g.Sex);
foreach(Person pp in g.Persons)
{
Console.Write("{0},", pp.name);
}
Console.WriteLine();
}
可以得到以下结果:
/*
Male are:
Peter,Tom,Ken
Female are:
Sue,Linda
*/
v. OrderBy、ThenBy
Order by作用和SQL中一样,可指定升序和降序,linq表达式的orderby支持多字段排序。如下:
var orderByQ = from p in persons
order by p.sex descending, p.name descending
select p; Console.WriteLine("The person after order by sex and name");
foreach( var p in orderByQ)
{
Console.Wirte("{0}," p.name);
}
Console.WirteLine();
输出为:
/*
The person after order by sex and name
Sue,Linda,Tom,Peter,Ken, */
注:这里之所以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的查询结果来转换,
Person[] personArr = orderByQ.ToArray();
List<Person> personList = orderByQ.ToList();
组内Linq培训记录的更多相关文章
- sql查询技巧,按时间分段进行分组,每半小时一组统计组内记录数量
今天拿到一个查询需求,需要统计某一天各个时间段内的记录数量. 具体是统计某天9:00至22:00时间段,每半小时内订单的数量,最后形成的数据形式如下: 时间段 订单数 9:00~9: ...
- VUE组内培训
最近去参加了一个外部VUE的周末培训,加上自己比较感兴趣所以对这项很热的前端框架做了点学习,顺便给组内同事做个简单的分享,希望下次有项目可以使用上- VUE的语法教程网上很多我就不一一列举,截图放一下 ...
- ROWNUMBER() OVER( PARTITION BY COL1 ORDER BY COL2)用法,先分组,然后在组内排名,分组计算,主表与附表一对多取唯一等
ROWNUMBER() OVER( PARTITION BY COL1 ORDER BY COL2)用法 今天在使用多字段去重时,由于某些字段有多种可能性,只需根据部分字段进行去重,在网上看到了row ...
- sql 分组后 组内排名
语法:ROW_NUMBER() OVER(PARTITION BY COLUMN ORDER BY COLUMN) 简单的说row_number()从1开始,为每一条分组记录返回一个数字,这里的ROW ...
- BIRT实现组内跨行计算
问题来源:http://developer.actuate.com/community/forum/index.php?/topic/36160-dealing-with-previous-rows- ...
- [SQL]用于提取组内最新数据,左连接,内连接,not exist三种方案中,到底谁最快?
本作代码下载:https://files.cnblogs.com/files/xiandedanteng/LeftInnerNotExist20191222.rar 人们总是喜欢给出或是得到一个简单明 ...
- 在论坛中出现的比较难的sql问题:29(row_number函数 组内某列的值连续出现3次标记出来)
原文:在论坛中出现的比较难的sql问题:29(row_number函数 组内某列的值连续出现3次标记出来) 在论坛中,遇到了不少比较难的sql问题,虽然自己都能解决,但发现过几天后,就记不起来了,也忘 ...
- group by分组后对组内数据进行排序
查询 每个班级英语成绩最高的前两名的记录 原文:https://www.cnblogs.com/hxfcodelife/p/10226934.html select a.Classid,a.Engli ...
- mysql单列去重复group by分组取每组前几条记录加order by排序
mysql分组取每组前几条记录(排名) 附group by与order by的研究,需要的朋友可以参考下 --按某一字段分组取最大(小)值所在行的数据 复制代码代码如下: /* 数据如下: name ...
随机推荐
- asp.net各种cookie代码和解析
Cookie是一段文本信息,在客户端存储 Cookie 是 ASP.NET 的会话状态将请求与会话关联的方法之一.Cookie 也可以直接用于在请求之间保持数据,但数据随后将存储在客户端并随每个请求一 ...
- iOS 阶段学习第七天笔记(函数、递归)
iOS学习(C语言)知识点整理笔记 一.函数 1)概念:具有特定功能的代码块的封装 2)函数的定义: 函数类型+函数名(形参列表) 函数类型 函数名(形参类型1 形参名1,形参类型2 形参名2 ...
- MVC之前的那点事儿系列(9):MVC如何在Pipeline中接管请求的?
文章内容 上个章节我们讲到了,可以在HttpModules初始化之前动态添加Route的方式来自定义自己的HttpHandler,最终接管请求的,那MVC是这么实现的么?本章节我们就来分析一下相关的M ...
- 使用MySQL Workbench导出MySQL数据库关系图
1. 点击MySQL Workbench中间Data Modeling下的Create EER Model From Existing Database: 2. 在Stored Connection中 ...
- MurmurHash算法:高运算性能,低碰撞率的hash算法
MurmurHash算法:高运算性能,低碰撞率,由Austin Appleby创建于2008年,现已应用到Hadoop.libstdc++.nginx.libmemcached等开源系统.2011年A ...
- IOS 2D游戏开发框架 SpriteKit-->续(postion,锚点,游戏滚动场景)
一. Postion 这里的postion和app开发中的layer.postion是一样的,postion的值代表该视图在父节点中的相对位置, 比如一个试图的父节点是self.view, 这里我们想 ...
- Scalaz(38)- Free :Coproduct-Monadic语句组合
很多函数式编程爱好者都把FP称为Monadic Programming,意思是用Monad进行编程.我想FP作为一种比较成熟的编程模式,应该有一套比较规范的操作模式吧.因为Free能把任何F[A]升格 ...
- ❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️html,js随笔。❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️
a标签本身的文字居中. a{ display:block; text-align:center; } 设置div1在另一个div2里居中,(写了左边margin 就别写右边了不然ie6有毛病,当然本身 ...
- Java集合源码分析(四)Vector<E>
Vector<E>简介 Vector也是基于数组实现的,是一个动态数组,其容量能自动增长. Vector是JDK1.0引入了,它的很多实现方法都加入了同步语句,因此是线程安全的(其实也只是 ...
- python 实现登陆接口
要求: 1.输入用户名密码 2.认证成功后显示欢迎信息 3.输入三次后,锁定账户 流程图: 代码实现: #!/usr/bin/env python #!-*- coding:utf-8 -*- #!- ...