当前位置: 首页 > news >正文

LINQ常用扩展方法、委托、Lambda、yield

LINQ让数据处理变得简单

文章目录

    • Where方法
    • Count()方法
    • Any()方法
    • 获取一条数据(是否带参数的两种写法)
      • Single
      • SingleOrDefault
      • First
      • FirstOrDefault
    • 排序
      • 多规则排序
    • 限制结果集,获取部分数据
    • 聚合函数
    • 分组
    • 投影
    • 匿名类型
    • 集合转换
    • 查询语法
    • 委托
      • Lambda表达式
      • LINQ
      • yield return

Where方法

 每一项数据都会经过predicate的测试,如果针对一个元素,predicate执行的返回值为true,那么这个元素就会放到返回值中。
Where参数是一个lambda表达式格式的匿名方法,方法的参数e表示当前判断的元素对象。参数的名字不一定非要叫e,不过一般lambda表达式中的变量名长度都不长。

 static void Main(string[] args){List<Employee> list = new List<Employee>();list.Add(new Employee { Id = 1, Name = "张三", Age = 30, Gender = false, Salary = 3500});list.Add(new Employee { Id = 2, Name = "李四", Age = 48, Gender = false, Salary = 6000});list.Add(new Employee { Id = 3, Name = "王五", Age = 16, Gender = true, Salary = 2800});list.Add(new Employee { Id = 4, Name = "赵六", Age = 16, Gender = false, Salary = 4100});list.Add(new Employee { Id = 5, Name = "田七", Age = 33, Gender = true, Salary = 3000});IEnumerable<Employee> items = list.Where(e => e.Age > 40);foreach (var item in items){Console.WriteLine(item);}}class Employee{public long Id { get; set; }public string Name { get; set; }//姓名public int Age { get; set; }//年龄public bool Gender { get; set; }//性别public int Salary { get; set; }//月薪public override string ToString(){return $"Id={Id},Name={Name},Age={Age},Gender={Gender},Salary={Salary}";}}

Count()方法

获取数据条数

int count1 = list.Count(e => e.Salary > 5000 || e.Age < 30);
int count2 = list.Where(e => e.Salary > 5000 || e.Age < 30).Count();

Any()方法

是否至少有一条数据

bool b1 = list.Any(e => e.Salary > 8000);
bool b2 = list.Where(e => e.Salary > 8000).Any();

比Count()实现效率高。

获取一条数据(是否带参数的两种写法)

Single

有且只有一条满足要求的数据,如果都不满足或者满足多条数据则抛出异常。

Employee e1= list.Where(e => e.Id == 4).Single();
Employee e2= list.Single(e => e.Id == 4);
Console.WriteLine(e2);

SingleOrDefault

最多只有一条满足要求的数据,如果都不满足返回默认值,如果满足多条则抛出异常。

Employee e2 = list.SingleOrDefault(e => e.Id == 4);
Employee e3 = list.SingleOrDefault(e => e.Id == 10);
Console.WriteLine(e3 == null);

First

至少有一条,返回第一条,如果都不满足抛出异常

Employee e4 = list.First(e => e.Age > 30);
Employee e5 = list.First(e => e.Age > 100);

FirstOrDefault

返回第一条或者默认值

Employee e6 = list.FirstOrDefault(e => e.Age > 100);
Console.WriteLine(e6 == null);

排序

Order() 对数据正序排序;

list.OrderBy(e => e.Age);

OrderByDescending() 倒序排序;

IEnumerable<Employee>  list2= list.OrderByDescending(e => e.Age);

用Guid或者随机数进行随机排序:

IEnumerable<Employee>  list2= list.OrderBy(e => Guid.NewGuid());Random random = new Random(); 
IEnumerable<Employee>  list2= list.OrderBy(e => random.Next());

按照最后一个字符排序:

IEnumerable<Employee>  list2= list.OrderBy(e => e.Name[e.Name.Length - 1]);

多规则排序

可以在Order()OrderByDescending()后继续写ThenBy ()ThenByDescending()
优先按照Age排序,如果Age相同再按照Salary排序

list.OrderBy(e => e.Age).ThenByDescending(e => e.Salary)
// 千万不要写成
// list.OrderBy(e => e.Age).OrderByDescending(e => e.Salary)

限制结果集,获取部分数据

Skip(n)跳过n条数据,Take(n)获取n条数据。
获取从第2条开始获取3条数据:

var orderedItems1 = list.Skip(2).Take(3);

Skip()Take()也可以单独使用。

var orderedItems1 = list.Skip(2);
var orderedItems2 = list.Take(3);

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

聚合函数

Max()Min()Average()Sum()Count()

//最大年龄
int a = list.Max(e => e.Age);
//最小年龄
int a = list.Min(e => e.Age);//年龄大于等于30岁的平均年龄
double b = list.Where(e => e.Age >= 30).Average(e => e.Age);//集合中所有年龄的和
int sum = list.Sum(e => e.Age);
//集合个数
int count = list.Count();

分组

GroupBy()方法参数是分组条件表达式,返回值为IGrouping<TKey, TSource>类型的泛型IEnumerable,也就是每一组以一个IGrouping对象的形式返回。IGrouping是一个继承自IEnumerable的接口,IGroupingKey属性表示这一组的分组数据的值。

IEnumerable<IGrouping<int, Employee>> g = list.GroupBy(x => x.Age);
foreach (IGrouping<int, Employee> item in g)
{Console.WriteLine(item.Key);foreach (var e in item){Console.WriteLine(e);}} 

投影

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

IEnumerable<int> ages = list.Select(e => e.Age);
IEnumerable<string> names = list.Select(e=>e.Gender?"男":"女");
var dogs = list.Select(p=>new Dog{NickName=e.Name,Age=e.Age});

匿名类型

var p = new {Name="tom", Id=1};
//属性名称一样时,可以省略
var p1 = new {name, Id=1, p.Age};
var select = list.Select(e => new { NianLing = e.Age, XingBie = e.Gender ? "男" : "女" });
foreach (var item in select)
{Console.WriteLine(item.NianLing + "," + item.XingBie);
}      
var items = list.GroupBy(e => e.Gender).Select(g=>new { Gender=g.Key,Count=g.Count(),AvgSalary= g.Average(e => e.Salary),MinAge= g.Min(e => e.Age)});

通过反编译软件查看dll文件,编译器最后也是生成了具体的类,只不过这个类名是编译器自动生成的。

集合转换

 有一些地方需要数组类型或者List类型的变量,可以用ToArray()方法和ToList()分别把IEnumerable<T>转换为数组类型和List<T>类型。

查询语法

 使用Where、OrderBy、Select等 扩展方法进行数据查询的写法叫做 “LINQ方法语法”。还有一种“查询语法”的写法。

var items2 = from e in listwhere e.Salary > 3000orderby e.Ageselect new { e.Name, e.Age, Gender = e.Gender ? "男" : "女" };
//等同于以下写法
var items3 = list.Where(e => e.Salary > 3000).OrderBy(e => e.Age).Select(e => new { e.Name, e.Age, Gender = e.Gender ? "男" : "女" });

Tips:日常开发推荐方法语法

统计一个字符串中每个字母出现的频率(忽略大小写),然后按照从高到低的顺序输出出现频率高于2次的单词和其出现的频率:

var items = s.Where(c => char.IsLetter(c))//过滤非字母.Select(c => char.ToLower(c))//大写字母转换为小写.GroupBy(c => c)//根据字母进行分组.Where(g=>g.Count()>2)//过滤掉出现次数<=2.OrderByDescending(g => g.Count())//按次数排序.Select(g=>new { Char=g.Key,Count=g.Count()});

委托

1、委托是可以指向方法的类型,调用委托变量时执行的就是变量指向的方法。

static void Main(string[] args)
{D1 d = F1;d();
}
static void F1()
{Console.WriteLine("hello");
}
delegate void D1();

匿名方法

static void Main(string[] args)
{Action a = delegate() {Console.WriteLine("hello world");};a();
}
static void Main(string[] args)
{Action a = delegate() {Console.WriteLine("hello world");};Func<int, int, int> func = delegate (int a, int b){return a + b;};Console.WriteLine(func(1, 2));
}

Lambda表达式

Func<int, int, string> f1 = (i1,i2) =>{return $"{i1}+{i2}={i1 + i2}";
};
  • 可以省略参数数据类型,因为编译能根据委托类型推断出参数的类型,用=>引出来方法体。
  • 如果委托没有返回值,且方法体只有一行代码,可省略 {}
  • 如果=>之后的方法体中只有一行代码,且方法有返回值,那么可以省略方法体的{}以及return。
  • 如果只有一个参数,参数的()可以省略。

2、.NET 中定义了泛型委托Action(无返回值)和Func(有返回值),所以一般不用自定义委托类型。

static void Main(string[] args)
{Action a = F1;a();
}
static void F1()
{Console.WriteLine("hello");
}
static void Main(string[] args)
{Func<int, int, int> func = F2;int sum = func(2, 5);Console.WriteLine(sum);
}
static int F2(int a, int b)
{return a + b;
}

LINQ

筛选出数组中大于3的数字:

IEnumerable<int> ints = [ 2,3,4,5,5];
IEnumerable<int> result = ints.Where(a => a > 3);

通过编写扩展方法MyWhere来模拟Where的实现:

static void Main(string[] args)
{IEnumerable<int> ints = [ 2,3,4,5,5];//IEnumerable<int> result = ints.Where(a => a > 3);IEnumerable<int> result = MyWhere(ints, a => a > 3);foreach (var item in result){Console.WriteLine(item);}
}static IEnumerable<int> MyWhere(IEnumerable<int> ints, Func<int, bool> func)
{List<int> result = new List<int>();foreach (var item in ints){if(func(item)) result.Add(item);}return result;
}

yield return

通过yield return来让MyWhere“流水线”处理:

static void Main(string[] args)
{IEnumerable<int> ints = [ 2,3,4,5,5];//IEnumerable<int> result = ints.Where(a => a > 3);IEnumerable<int> result = MyWhere(ints, a => a > 3);foreach (var item in result){Console.WriteLine(item);}
}
static IEnumerable<int> MyWhere(IEnumerable<int> ints, Func<int, bool> func)
{List<int> result = new List<int>();foreach (var item in ints){if(func(item)) yield return item;}
}

相关文章:

  • 汽车信息安全--密钥管理系统初探(2)
  • GraalVM详细安装及打包springboot、java、javafx使用教程(打包普通JAVA项目篇)
  • Python 指南-最短路径(Dijkstra 算法):
  • 【微服务】Spring Boot 版本升级到 2.7.18
  • Web安全基础入门+信息收集篇
  • 3.21 ARM day5
  • Java学习笔记01
  • 基于ssm的学生选课管理系统的设计与实现
  • 基于ssm的酒店民宿管理系统的设计与实现
  • JAVA面向对象编程 JAVA语言入门基础
  • 【机器学习-07】逻辑回归(Logistic Regression)的介绍和python实现
  • LeetCode 1027——最长等差数列
  • 开源流程图表库(02):Draw.io在线绘制各类图表,导出html使用
  • 【jvm】jinfo使用
  • javaSwing宿舍管理系统(三个角色)
  • 【EOS】Cleos基础
  • Android 架构优化~MVP 架构改造
  • android图片蒙层
  • fetch 从初识到应用
  • JavaScript 无符号位移运算符 三个大于号 的使用方法
  • Mysql数据库的条件查询语句
  • Netty源码解析1-Buffer
  • PHP 的 SAPI 是个什么东西
  • vue学习系列(二)vue-cli
  • web标准化(下)
  • Zsh 开发指南(第十四篇 文件读写)
  • 初识 beanstalkd
  • 给第三方使用接口的 URL 签名实现
  • 给新手的新浪微博 SDK 集成教程【一】
  • 基于web的全景—— Pannellum小试
  • 入门级的git使用指北
  • 提醒我喝水chrome插件开发指南
  • 我是如何设计 Upload 上传组件的
  • 移动端解决方案学习记录
  • 最简单的无缝轮播
  • mysql 慢查询分析工具:pt-query-digest 在mac 上的安装使用 ...
  • 阿里云移动端播放器高级功能介绍
  • 如何用纯 CSS 创作一个菱形 loader 动画
  • ​Base64转换成图片,android studio build乱码,找不到okio.ByteString接腾讯人脸识别
  • # 数据结构
  • (4)事件处理——(2)在页面加载的时候执行任务(Performing tasks on page load)...
  • (day6) 319. 灯泡开关
  • (八)光盘的挂载与解挂、挂载CentOS镜像、rpm安装软件详细学习笔记
  • (顶刊)一个基于分类代理模型的超多目标优化算法
  • (二)JAVA使用POI操作excel
  • (附源码)ssm高校社团管理系统 毕业设计 234162
  • (附源码)流浪动物保护平台的设计与实现 毕业设计 161154
  • (转)GCC在C语言中内嵌汇编 asm __volatile__
  • (转)程序员疫苗:代码注入
  • **CI中自动类加载的用法总结
  • ./include/caffe/util/cudnn.hpp: In function ‘const char* cudnnGetErrorString(cudnnStatus_t)’: ./incl
  • .htaccess配置常用技巧
  • .NET BackgroundWorker
  • .NET Core 中插件式开发实现
  • .NET MVC第三章、三种传值方式