- LINQ的意义:可以是数据处理变的简单
- LINQ的由来,从lambda表达式,指向了一个匿名方法
- LINQ.Where()方法实现: static IEnumerable
MyWhere(this IEnumerable source,Func func){ foreach(var item in source){ if(fun(item)){yield return item;}} - LINQ常用的扩展方法:
- Where查询语句
- Count计数
- Single First 满足条件
- Order 排序
- Skip Take 跳过取
- 聚合函数
- 分组GroupBy IGrouping
- Select投影操作,把数据投影到自己想要的实例上,支持匿名类型
- 查询语法 from item in list orderby xxxx等
LINQ的意义
让数据处理变的简单,和python中NumPy类库功能相似。委托(Action Func—lambda-linq ```csharp
static void Main(string[] args){ string s = “adbdfaghagkaewqrwosfbafaof1214afhkaf”; var items = s.Where(c => char.IsLetter(c))//过滤非字母 .Select(c => char.ToUpper(c))//全部转换为大写 .GroupBy(c => c)//根据字母进行分组 这里变成了类似字典的东西 .Where(g => g.Count() > 2)//过滤掉出现次数<=2的字符 .OrderByDescending(g => g.Count())//按次序降序排序 .Select(g => new { Char = g.Key, Count = g.Count() }); foreach (var item in items) { Console.WriteLine(item.Char); Console.WriteLine(item.Count); } }
delegate void TestDelegate(); //委托是一个类型,需要创建实例,同步调用、异步调用(容易造成资源竞争) TestDelegate testDelegate = new TestDelegate(F1); testDelegate = F1;//这样直接赋值也可以,委托testDelegate指向F1方法,方法的指针,方法模板。 testDelegate.Invoke();
static void F1(){ Console.WriteLine(“我是F1”); }
<a name="DHP7u"></a># Lambda 委托指向匿名方法委托指向匿名方法(lambda)- 如果=>之后的方法体中**只有一行代码**,且方法有返回值,可以省略大括号和return- 如果**只有一个参数**()可以省略```csharpFunc<int,int,string> f1 = delegate(int i1,int i2){return $"{i1}+{i2}={i1+i2}";}string s = f1(1,2);//演变Func<int, int, string> func = (a, b) => { return $"{a + b}"; };Console.WriteLine(func(1,2));//省略(只有一行代码)Func<int, int, string> func = (a, b) =>$"{a + b}";Console.WriteLine(func(1,2));//省略(只有一个参数)Func<int, string> func = a=>$"{a}";Console.WriteLine(func(1,2));
自我实现LINQ.Where
var nums = new int[] { 1, 2, 3, 54, 643, 63, 7, 78 };var tmp = nums.Where(i => i > 10);tmp = MyWhere(nums,a=>a>10);tmp = nums.MyWhereKuo(a=>a>10);static IEnumerable<int> MyWhere(IEnumerable<int> items,Func<int,bool> func){foreach (var item in items){if (func(item)){yield return item;}}}//扩展方法:public static修饰,this关键字,this后的类型都可以.出来此静态方法 包含扩展方法的类必须是静态类public static IEnumerable<int> MyWhereKuo(this IEnumerable<int> items,Func<int,bool> func){foreach (var item in items){if (func(item)){yield return item;}}}
LINQ常用扩展方法
LINQ中提供了大量类似Where的扩展方法,简化数据处理。大部分都在System.Linq命名空间中。
Where方法:查询
public static IEnumerable
Lambda:委托指向匿名方法
这里面枚举迭代source内容,泛型委托,当方法满足这个泛型委托约束即可(匿名方法)传入迭代的元素,返回值为bool类型,用于判断条件是否满足。
using System;using System.Collections.Generic;namespace AlbertLINQ{public static class Program{static void Main(string[] args){List<Student> stuList = new List<Student>(){new Student(){Name="Albert",Age=24,Height=175},new Student(){Name="Jack",Age=22,Height=180},new Student(){Name="Doris",Age=28,Height=165}};var stuSortList = stuList.AlbertWhere(x=>x.Age>25);foreach(var item in stuSortList){System.Console.WriteLine(item.Name);}}static IEnumerable<TSource> AlbertWhere<TSource>(this IEnumerable<TSource> source,Func<TSource,bool> func){foreach(var item in source){if(func(item)){yield return item;}}}}public class Student{public string Name { get; set; }public int Age { get; set; }public double Height { get; set; }}}
Count()方法:获取满足条件的数据条数
两种写法:
//写法一:直接Countint count = list.Count(a=>a.Age<30);//写法二:先Where筛选后再Countint countTwo = list.Where(a=>a.Age<30).Count();public static int Count<TSource>(this IEnumerable<TSource> source)public static int Count<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
Any()方法:是否至少有一条数据(比Count后再比较效率高)
List<Student> stuList = new List<Student>(){new Student(){Age=24,Name="Albert",Height=176},new Student(){Age=25,Name="Jack",Height=178},new Student(){Age=28,Name="Doris",Height=165}};var anyList = stuList.Any();Console.WriteLine(anyList); //TrueanyList = stuList.Any(x => x.Age > 36);Console.WriteLine(anyList);//False
Single() SingleOrDefault() First() FirstOrDefault() 获取一条数据(是否带参数的两种写法)—防御性编程(避免问题越来越大)
Single:有且只有一条满足要求的数据(唯一一个 SingleDog单身狗) 不能返回默认值,必须有一条 =1
SingleOrDefault:最多只有一条满足要求的数据 <=1
First:至少有一条,返回第一条 不能返回默认值,必须有一条 >=1
FirstOrDefault:返回第一条或者默认值
Order() 排序
Order():对数据正序排序
OrderByDescending()倒叙排序
//倒序排序var stuSortList2 = stuList.OrderByDescending(e => e.Age);//随机排序var stuSortList3 = stuList.OrderByDescending(e => Guid.NewGuid());
多规则排序
ThenBy()
ThenByDescending()
var stuSortList4 = stuList.OrderByDescending(e =>e.Name[e.Name.Length-1]).ThenBy(e=>e.Height);
Skip() Take() 限制结果集,获取部分数据—用于分页
Skip(n)跳过n条数据,Take(n)获取n条数据
获取从第二条数据开始的三条数据 var orderedItem = list.Skip(2).Take(3);
var stuSortList5 = stuList.OrderByDescending(e => e.Name[e.Name.Length - 1]).ThenBy(e => e.Height).Skip(2).Take(2);
聚合函数 Max() Min() Average() Sum() Count()
LINQ中所有扩展方法几乎都是针对IEnumerable接口的,而几乎所有能返回集合的都返回IEnumerable,所以是可以把几乎所有方法“链式使用”的。
var stuSortList6 = stuList.Max(e => e.Age);//返回年龄集合年龄的最大值
分组 GroupBy()
GroupBy()方法参数是分组条件表达式,返回值为IGrouping
排序后foreach取到的Item是IGrouping
List<Student> stuList = new List<Student>(){new Student(){Age=24,Name="Albert",Height=176},new Student(){Age=25,Name="Jack",Height=178},new Student(){Age=28,Name="Doris",Height=165},new Student(){Age=24,Name="Lucy",Height=176},new Student(){Age=25,Name="Boris",Height=180},new Student(){Age=28,Name="Dobin",Height=169}};var groupStu = stuList.GroupBy(x => x.Age);foreach (var item in groupStu){//外层循环获取到的是IGroup对象,里面有的是IGrouping<int,Student> int是Key值,分组的K值Console.WriteLine(item.Key);Console.WriteLine(item.Max(g=>g.Height));//每一组是一个集合,是集合就可以用聚合函数,这边把//每一组里面的身高最大值取出来Console.WriteLine(item.Average(g=>g.Height));//平均身高foreach (var stu in item){Console.WriteLine(stu.Name);}Console.WriteLine("===========");}Console.ReadLine();
投影操作 Select
把集合中的每一项转换为另外一种类型。
var stuSelect = stuList.Select(e => e.Age+""+e.Height);//将所有的Age+Height取出来 IEnumerable<sting>var stuSelect2 = stuList.Select(e => e.Age);//将所有的Age取出来 IEnumerable<int>var stuSelect3 = stuList.Where(e=>e.Age>25).Select(e => e.Age+","+e.Height);//将所有的Age取出来
匿名类型—在编译时生成,ILSpy
var p = new {Name=”Tom”,Id = 1}
var stuSelect3 = stuList.Select(e => new { Name = "YangZhongKe", Age = 50 });//匿名类型foreach (var item in stuSelect3){Console.WriteLine(item.ToString());}//打印结果,stuList长度为6,每一个都替换成new出来的匿名类型{ Name = YangZhongKe, Age = 50 }{ Name = YangZhongKe, Age = 50 }{ Name = YangZhongKe, Age = 50 }{ Name = YangZhongKe, Age = 50 }{ Name = YangZhongKe, Age = 50 }{ Name = YangZhongKe, Age = 50 }
集合转换
ToArray() ToList()分别把IEnumerable
查询语法—掌握方法语法即可
var item = from e in list
where e.Salary>3000
orderby e.Age
select new{e.Name,e.Age,Gender=e.Gender?”男”:”女”};
LIQN面试问题
面试时候的算法题一般避免使用正则表达式、LINQ等这些高级的类库。
using System;using System.Collections.Generic;using System.Linq;namespace ApplyLINQ{class Program{static void Main(string[] args){CaseOne();CaseTwo();Console.ReadLine();}//有一个用逗号分隔的表示成绩的字符串,如"61,90,100,//99,18,22,38,66,80,93,55,50,89//计算这些成绩的平均值static void CaseOne(){string str = "61,90,100,99,18";var average = str.Split(',').Average(e => int.Parse(e));Console.WriteLine(average);}//统计一个字符串中每个字母出现的频率(忽略大小写),然后按照从高到低的顺序输出//出现频率高于2次的单词和其出现频率static void CaseTwo(){string str = "abcdabcdabcAaBczdhkguiahgadklg";var tmp = str.ToUpper().GroupBy(c => c);foreach (var value in tmp){Console.WriteLine(value.Key);Console.WriteLine(value.Count());foreach (var value2 in value){Console.WriteLine(value2);}Console.WriteLine("============");}Console.WriteLine("xxxxxxxxxxx");var word = str.ToUpper().GroupBy(c => c).Select(g => new { DC = g.Key, PL = g.Count() }).OrderByDescending(c => c.PL).Where(c => c.PL > 2);foreach (var item in word){Console.WriteLine(item.ToString());}}}}
