• 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常用的扩展方法:
  1. Where查询语句
  2. Count计数
  3. Single First 满足条件
  4. Order 排序
  5. Skip Take 跳过取
  6. 聚合函数
  7. 分组GroupBy IGrouping
  8. Select投影操作,把数据投影到自己想要的实例上,支持匿名类型
  9. 查询语法 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”); }

  1. <a name="DHP7u"></a>
  2. # Lambda 委托指向匿名方法
  3. 委托指向匿名方法(lambda)
  4. - 如果=>之后的方法体中**只有一行代码**,且方法有返回值,可以省略大括号和return
  5. - 如果**只有一个参数**()可以省略
  6. ```csharp
  7. Func<int,int,string> f1 = delegate(int i1,int i2){return $"{i1}+{i2}={i1+i2}";}
  8. string s = f1(1,2);
  9. //演变
  10. Func<int, int, string> func = (a, b) => { return $"{a + b}"; };
  11. Console.WriteLine(func(1,2));
  12. //省略(只有一行代码)
  13. Func<int, int, string> func = (a, b) =>$"{a + b}";
  14. Console.WriteLine(func(1,2));
  15. //省略(只有一个参数)
  16. Func<int, string> func = a=>$"{a}";
  17. Console.WriteLine(func(1,2));

自我实现LINQ.Where

  1. var nums = new int[] { 1, 2, 3, 54, 643, 63, 7, 78 };
  2. var tmp = nums.Where(i => i > 10);
  3. tmp = MyWhere(nums,a=>a>10);
  4. tmp = nums.MyWhereKuo(a=>a>10);
  5. static IEnumerable<int> MyWhere(IEnumerable<int> items,Func<int,bool> func)
  6. {
  7. foreach (var item in items)
  8. {
  9. if (func(item))
  10. {
  11. yield return item;
  12. }
  13. }
  14. }
  15. //扩展方法:public static修饰,this关键字,this后的类型都可以.出来此静态方法 包含扩展方法的类
  16. 必须是静态类
  17. public static IEnumerable<int> MyWhereKuo(this IEnumerable<int> items,Func<int,bool> func)
  18. {
  19. foreach (var item in items)
  20. {
  21. if (func(item))
  22. {
  23. yield return item;
  24. }
  25. }
  26. }

LINQ常用扩展方法

LINQ中提供了大量类似Where的扩展方法,简化数据处理。大部分都在System.Linq命名空间中。

Where方法:查询

public static IEnumerable Where(this IEnumerable source,Func predicate);
Lambda:委托指向匿名方法
这里面枚举迭代source内容,泛型委托,当方法满足这个泛型委托约束即可(匿名方法)传入迭代的元素,返回值为bool类型,用于判断条件是否满足。

  1. using System;
  2. using System.Collections.Generic;
  3. namespace AlbertLINQ
  4. {
  5. public static class Program
  6. {
  7. static void Main(string[] args)
  8. {
  9. List<Student> stuList = new List<Student>(){
  10. new Student(){Name="Albert",Age=24,Height=175},
  11. new Student(){Name="Jack",Age=22,Height=180},
  12. new Student(){Name="Doris",Age=28,Height=165}
  13. };
  14. var stuSortList = stuList.AlbertWhere(x=>x.Age>25);
  15. foreach(var item in stuSortList){
  16. System.Console.WriteLine(item.Name);
  17. }
  18. }
  19. static IEnumerable<TSource> AlbertWhere<TSource>(this IEnumerable<TSource> source,Func<TSource,bool> func){
  20. foreach(var item in source){
  21. if(func(item)){
  22. yield return item;
  23. }
  24. }
  25. }
  26. }
  27. public class Student{
  28. public string Name { get; set; }
  29. public int Age { get; set; }
  30. public double Height { get; set; }
  31. }
  32. }

Count()方法:获取满足条件的数据条数

两种写法:

  1. //写法一:直接Count
  2. int count = list.Count(a=>a.Age<30);
  3. //写法二:先Where筛选后再Count
  4. int countTwo = list.Where(a=>a.Age<30).Count();
  5. public static int Count<TSource>(this IEnumerable<TSource> source)
  6. public static int Count<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)

Any()方法:是否至少有一条数据(比Count后再比较效率高)

  1. List<Student> stuList = new List<Student>()
  2. {
  3. new Student(){Age=24,Name="Albert",Height=176},
  4. new Student(){Age=25,Name="Jack",Height=178},
  5. new Student(){Age=28,Name="Doris",Height=165}
  6. };
  7. var anyList = stuList.Any();
  8. Console.WriteLine(anyList); //True
  9. anyList = stuList.Any(x => x.Age > 36);
  10. Console.WriteLine(anyList);//False

Single() SingleOrDefault() First() FirstOrDefault() 获取一条数据(是否带参数的两种写法)—防御性编程(避免问题越来越大)

Single:有且只有一条满足要求的数据(唯一一个 SingleDog单身狗) 不能返回默认值,必须有一条 =1
SingleOrDefault:最多只有一条满足要求的数据 <=1
First:至少有一条,返回第一条 不能返回默认值,必须有一条 >=1
FirstOrDefault:返回第一条或者默认值

Order() 排序

Order():对数据正序排序
OrderByDescending()倒叙排序

  1. //倒序排序
  2. var stuSortList2 = stuList.OrderByDescending(e => e.Age);
  3. //随机排序
  4. var stuSortList3 = stuList.OrderByDescending(e => Guid.NewGuid());

多规则排序
ThenBy()
ThenByDescending()

  1. var stuSortList4 = stuList.OrderByDescending(e =>e.Name[e.Name.Length-1]).ThenBy(
  2. e=>e.Height);

Skip() Take() 限制结果集,获取部分数据—用于分页

Skip(n)跳过n条数据,Take(n)获取n条数据
获取从第二条数据开始的三条数据 var orderedItem = list.Skip(2).Take(3);

  1. var stuSortList5 = stuList.OrderByDescending(e => e.Name[e.Name.Length - 1]).ThenBy(
  2. e => e.Height).Skip(2).Take(2);

聚合函数 Max() Min() Average() Sum() Count()

LINQ中所有扩展方法几乎都是针对IEnumerable接口的,而几乎所有能返回集合的都返回IEnumerable,所以是可以把几乎所有方法“链式使用”的。

  1. var stuSortList6 = stuList.Max(e => e.Age);//返回年龄集合年龄的最大值

分组 GroupBy()

GroupBy()方法参数是分组条件表达式,返回值为IGrouping类型的泛型IEnumerable,也就是每一组以一个IGrouping对象的形式返回。IGrouping是一个继承自IEnumerable的接口,IGrouping中的Key属性表示这一组的分组数据的值。例如:根据年龄分组,获取每组人数、最高工资、最低工资、平均工资。
排序后foreach取到的Item是IGrouping类型,这里可以类比为一个字典,TKey为分组关键字,TSource为分组的实际对象。

  1. List<Student> stuList = new List<Student>()
  2. {
  3. new Student(){Age=24,Name="Albert",Height=176},
  4. new Student(){Age=25,Name="Jack",Height=178},
  5. new Student(){Age=28,Name="Doris",Height=165},
  6. new Student(){Age=24,Name="Lucy",Height=176},
  7. new Student(){Age=25,Name="Boris",Height=180},
  8. new Student(){Age=28,Name="Dobin",Height=169}
  9. };
  10. var groupStu = stuList.GroupBy(x => x.Age);
  11. foreach (var item in groupStu)
  12. {
  13. //外层循环获取到的是IGroup对象,里面有的是IGrouping<int,Student> int是Key值,分组的K值
  14. Console.WriteLine(item.Key);
  15. Console.WriteLine(item.Max(g=>g.Height));//每一组是一个集合,是集合就可以用聚合函数,这边把
  16. //每一组里面的身高最大值取出来
  17. Console.WriteLine(item.Average(g=>g.Height));//平均身高
  18. foreach (var stu in item)
  19. {
  20. Console.WriteLine(stu.Name);
  21. }
  22. Console.WriteLine("===========");
  23. }
  24. Console.ReadLine();

投影操作 Select

把集合中的每一项转换为另外一种类型。

  1. var stuSelect = stuList.Select(e => e.Age+""+e.Height);//将所有的Age+Height取出来 IEnumerable<sting>
  2. var stuSelect2 = stuList.Select(e => e.Age);//将所有的Age取出来 IEnumerable<int>
  3. var stuSelect3 = stuList.Where(e=>e.Age>25).Select(e => e.Age+","+e.Height);//将所有的Age取出来

匿名类型—在编译时生成,ILSpy
var p = new {Name=”Tom”,Id = 1}

  1. var stuSelect3 = stuList.Select(e => new { Name = "YangZhongKe", Age = 50 });//匿名类型
  2. foreach (var item in stuSelect3)
  3. {
  4. Console.WriteLine(item.ToString());
  5. }
  6. //打印结果,stuList长度为6,每一个都替换成new出来的匿名类型
  7. { Name = YangZhongKe, Age = 50 }
  8. { Name = YangZhongKe, Age = 50 }
  9. { Name = YangZhongKe, Age = 50 }
  10. { Name = YangZhongKe, Age = 50 }
  11. { Name = YangZhongKe, Age = 50 }
  12. { Name = YangZhongKe, Age = 50 }

集合转换

ToArray() ToList()分别把IEnumerable类型转换为数组类型和List类型

查询语法—掌握方法语法即可

var item = from e in list
where e.Salary>3000
orderby e.Age
select new{e.Name,e.Age,Gender=e.Gender?”男”:”女”};

LIQN面试问题

面试时候的算法题一般避免使用正则表达式、LINQ等这些高级的类库。

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. namespace ApplyLINQ
  5. {
  6. class Program
  7. {
  8. static void Main(string[] args)
  9. {
  10. CaseOne();
  11. CaseTwo();
  12. Console.ReadLine();
  13. }
  14. //有一个用逗号分隔的表示成绩的字符串,如"61,90,100,
  15. //99,18,22,38,66,80,93,55,50,89
  16. //计算这些成绩的平均值
  17. static void CaseOne()
  18. {
  19. string str = "61,90,100,99,18";
  20. var average = str.Split(',').Average(e => int.Parse(e));
  21. Console.WriteLine(average);
  22. }
  23. //统计一个字符串中每个字母出现的频率(忽略大小写),然后按照从高到低的顺序输出
  24. //出现频率高于2次的单词和其出现频率
  25. static void CaseTwo()
  26. {
  27. string str = "abcdabcdabcAaBczdhkguiahgadklg";
  28. var tmp = str.ToUpper().GroupBy(c => c);
  29. foreach (var value in tmp)
  30. {
  31. Console.WriteLine(value.Key);
  32. Console.WriteLine(value.Count());
  33. foreach (var value2 in value)
  34. {
  35. Console.WriteLine(value2);
  36. }
  37. Console.WriteLine("============");
  38. }
  39. Console.WriteLine("xxxxxxxxxxx");
  40. var word = str.ToUpper().GroupBy(c => c).Select(g => new { DC = g.Key, PL = g.Count() }).
  41. OrderByDescending(c => c.PL).Where(c => c.PL > 2);
  42. foreach (var item in word)
  43. {
  44. Console.WriteLine(item.ToString());
  45. }
  46. }
  47. }
  48. }