赞
踩
常用集合类的拓展方法
LINQ关键的功能是提供了集合类的拓展方法,所有实现了IEnumberable 接口的类都可以使用这些方法,这些方法不是IEnumberable,而是以拓展方法的形式存在与System.Linq命名空间的静态类中。
这里定义一个用于测试的类
Employee{
public int Id {get;set;}
public string Name {get;set;}
public int Age {get;set;}
public bool Gender {get;set;}
public double Salary {get;set;}
}
数据过滤筛选
Where方法是用于根据条件对数据进行过滤的。
IEnumberable<Employee> list1 = list.Where(e => e.Salary > 2500 && e.Age < 34);
foreach(Employee e in list1)
{
Console.WriteLine(e);
}
获取数据条数
Count()方法用于获取数据条数,它有两个重载方法,一个没有参数,另一个有Func<TSource,bool>predicate类型参数。没有参数的重载方法用于获取集合的数据条数,而有predicate参数的可以获取集合中符合predicate条件的数据条数。
int count1 = list.Count(e => e.Salary > 5000 || e.Age < 30);
int count1 = list.Where(e => e.Salary > 5000 || e.Age < 30).Count();
判断是否至少有一条满足条件的数据
Any方法用于判断集合中是否至少有一条满足条件的数据,返回值为bool类型。Any方法同样有两个重载方法,一个没有参数的,一个是有Func<TSource,bool> predicate类型参数的。
bool b1 = list.Any(e => e.Salary > 8000)
bool b2 = list.Where(e => e.Salary > 8000).Any()
获取一条数据
LINQ中有4组获取一条数据的方法,分别是Single、SingleOrDefault、First、FirstOrDefault,返回的都是符合条件的一条数据
同样,每组方法有两个重载方法,一个没有参数,一个有Func<TSource,bool> predicate类型参数的。
区别
Single
如果确定有且仅有一条满足要求的数据那么就用Single方法。如果没有满足条件的数据,或者满足条件的数据多于一条,Single方法就会抛出异常SingleOrDefault
:如果确认最多只有一条满足要求的数据,那么就用SingleOrDefault方法。如果没有满足条件的数据,SingleOrDefault方法就会返回类型的默认值,如果满足条件的数据多于一条,SingleOrDefault就会抛出异常First
: 如果满足条件的数据有一条或者多条,First方法就会返回第一条数据,如果没有满足条件的数据,First方法就会抛出异常FirstOrDefault
:如果满足条件的数据有一条或者多条,FirstOrDefault方法就会返回第一条数据,如果没有满足条件的数据,FirstOrDefault方法就会满足返回类型的默认值代码演示
Employee e1 = list.Single(e => e.Id == 6)
Console.WriteLine(e1);
Employee? e2 = list.SinleOrDefault(e=>e.Id==9);
if(e2 == null)
Console.WriteLine("没有 Id == 9的数据");
else
Console.WriteLine(e2);
Employee e3 = list.First(e=>e.Age > 30);
Console.WriteLine(e3);
Employee? e4 = list.FirstOrDefault(e=>e.Id>9999);
if(e4 == null)
Console.WriteLine("没有大于30岁的数据");
else
Console.WriteLine(e4);
排序
OrderBy方法可以对数据进行正向排序,而OrderByDescending方法则可以对数据进行逆向排序
Console.WriteLine("-------按照年龄正序排序----------")
var orderedItem1 = list.OrderBy(e => e.Age);
foreach(var item in orderedItem1)
{
Console.WriteLine(item);
}
Console.WriteLine("-------按照年龄逆序排序----------")
var orderedItem2 = list.OrderByDescending(e => e.Age);
foreach(var item in orderedItem2)
{
Console.WriteLine(item);
}
限制结果集
限制结果集用来从集合中获取部分数据,其主要应用场景是分页查询,比如从第2条开始获取3条数。
Skip(n)方法用于跳过n条数据,Take(n)方法用于获取n条数据。
var orderedItem1 = list.Skip(2).Take(3);
foreach(var item in orderedItem1)
{
Console.WriteLine(item);
}
Skip、Take方法也可以单独使用
聚合函数
分组
GroupBy方法用来进行分组
IEnumberable<IGrouping<TKey,TSource>> GroupBy<TSource.TKey>(this IEnumberable<TSource> source,Func<TSource,TKey> keySelector())
GroupBy方法的参数keySelector是一个分组表达式,GroupBy方法的返回值为IGrouping<TKey,TSource>类型IEnumberable。IGrouping是一个继承自IEnumberable的接口,IGrouping中唯一的成员就是Key属性,表示这一组数据的数据项。
IEnumberable<IGrouping<int,Employee>> items = list.GroupBy(e=>e.Age);
foreach(IGrouping<int,Employee> item in items)
{
int age = item.Key;
int count = item.Count();
int maxSalary = item.Max(e=>e.Salary);
double avgSalary = item.Average(e=>e.Salary);
Console.WriteLine($"年龄{item.Key},人数{count},最高工资{maxSalary},平均工资{avgSalary}");
}
投影
可以对集合使用Select方法进行投影操作,通俗来说就是把集合中的每一项转换为另外一种类型,Select方法的参数就是转换的表达式
IEnumberable<int> ages = list.Select(e=> e.Age);
Console.WriteLine(string.Join(",",ages))
集合转换
集合操作的拓展方法返回值大多是IEnumberable类型,但是有一些地方需要数组类型或者List类型的变量,我们可以用ToArray和ToList方法分别把IEnumberable转换为数组和List类型
Employee[] items = list.Where(e=>e.Salary > 3000 ).ToArray();
List<Employee> items = list.Where(e=>e.Salary > 3000 ).ToList();
void QueryBooks(string searchWords,bool searchAll,boolorderByPrice,double upperPrice)
long pageCount(long)Math.Ceiling(count * 1.0 / pageSize);
void OutputPage(int pageIndex,int pageSize) { using TestDbContext ctx = new TestDbContext(); //这里先把查询规则创建出来 IQueryable<Book> books =ctx.Books.Where(b => !b.Title.Contains("张三")); //获取满足条件的数据总条数 long count =books.LongCount(); //使用count * 1.0 / pageSize 可以计算出数据总页数,考虑到有可能最后一页不满,使用Ceiling()取整 long pageCount = (long)Math.Ceiling(count * 1.0 / pageSize); Console.WriteLine("页数:"+pageCount); var pagedBooks = books.Skip((pageIndex - 1) * pageSize).Take(pageSize); foreach(var b in pageBooks) { Console.WriteLine(b.Id + ","+b.Title); } }
这里的pageIndex
代表页码,pageSize
参数代表页大小。考虑到pageIndex
序号是从1开始的,因此我们要使用Skip
方法跳过(pageIndex-1)*pageSize
条数据,再最多获取pageSize条数据,就可以获得正确的分页数据了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。