上篇C#语法之Linq查询基础一基本把Linq介绍了一下,这篇主要是列举下它的几个常见用法。
在用之前先准备些数据,新建了两个类Student、Score,并通过静态方法提供数据。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace LinqDemo { public class Student { public string StuId { get; set; } public string Name { get; set; } public int Age { get; set; } public Student(string stuId, string name,int age) { StuId = stuId; Name = name; Age = age; } public static List<Student> GetAllStudents() { List<Student> stus = new List<Student>() { new Student("001","xiaoming1",25), new Student("002","xiaoming2",24), new Student("003","xiaoming3",23), new Student("004","xiaoming4",26), new Student("005","xiaoming5",27), new Student("006","xiaoming1",25) }; return stus; } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace LinqDemo { public class Score { public string StuId { get; set; } public int Math { get; set; } public int English { get; set; } public int Chinese { get; set; } public Score(string stuId, int math, int english, int chinese) { StuId = stuId; Math = math; English = english; Chinese = chinese; } public static List<Score> GetAllScores() { List<Score> scores = new List<Score>() { new Score("001",85,90,85), new Score("002",85,90,85), new Score("003",60,70,65), new Score("004",59,99,75), new Score("005",66,90,65) }; return scores; } } }
一、筛选
where 是筛选lamdba表达式的,OfType<TResult>是筛选TResult类型的
int[] a = new int[] { 1, 3, 4, 6, 8, 7, 9, 1, 3, 2 }; var stus = Student.GetAllStudents().Where(p => p.StuId.Equals("001")); foreach (Student stu in stus) { Console.WriteLine("StuId:{0} Name:{1}", stu.StuId, stu.Name); } var result = a.Where((r, index) => r % 2 == 0 && index % 2 == 1); foreach (var s in result) { Console.WriteLine("{0}", s); } Console.WriteLine("--------------------------"); object[] data = { "one", 2, 3, "four", 5 }; //OfType 可隐式转换 sting可隐式转换为int int不可隐式转换为string 所以不能直接写OfType<string>() result = data.OfType<int>(); foreach (var s in result) { Console.WriteLine("{0}", s); }
二、改变元素顺序
Orderby thenby来进行排序,thenby可以使用多次来多条件排序
//单个排序 int[] a = new int[] { 1, 3, 4, 6, 8, 7, 9, 1, 3, 2 }; var result = a.OrderByDescending(p => p); foreach (var s in result) { Console.WriteLine("{0}", s); }
//多条件排序 var result = Student.GetAllStudents().OrderByDescending(p => p.StuId).ThenBy(p => p.Name); foreach (var s in result) { Console.WriteLine("StuId:{0} Name:{1}", s.StuId, s.Name); }
翻转
对于上面的查询后面加一个Reverse()方法则会将结果翻转。
var result = Student.GetAllStudents().OrderByDescending(p => p.StuId).ThenBy(p => p.Name).Reverse(); foreach (var s in result) { Console.WriteLine("StuId:{0} Name:{1}", s.StuId, s.Name); }
三、分组
分组常用作统计或查找重复。下面的例子就是查找姓名和年龄都相同的学生。
var result = from stu in Student.GetAllStudents() group stu by new { stu.Name, stu.Age } into g where g.Count() > 1 select new { g.Key.Name, g.Key.Age }; foreach (var s in result) { Console.WriteLine("Name:{0} Age:{1}", s.Name, s.Age); }
四、连接
左连接
var result = from stu in Student.GetAllStudents() join s in Score.GetAllScores() on stu.StuId equals s.StuId into joinStuScore from p in joinStuScore.DefaultIfEmpty() select new { StuId = stu.StuId, Name = stu.Name, Math = p == null ? 0 : p.Math, English = p == null ? 0 : p.English, Chinese = p == null ? 0 : p.Chinese }; foreach (var s in result) { Console.WriteLine("StuId:{0} Name:{1} Math:{2} English:{3} Chinese:{4}", s.StuId, s.Name, s.Math, s.English, s.Chinese); }
内连接
var result = from stu in Student.GetAllStudents() join s in Score.GetAllScores() on stu.StuId equals s.StuId select new { StuId = stu.StuId, Name = stu.Name, Math = s.Math, English = s.English, Chinese = s.Chinese }; foreach (var s in result) { Console.WriteLine("StuId:{0} Name:{1} Math:{2} English:{3} Chinese:{4}", s.StuId, s.Name, s.Math, s.English, s.Chinese); }
五、集合操作
下面是两个集合的交集、差集和并集,至于distinct这个之前有专门讲解。
int[] a = {1,3,5,2 }; int[] b = { 1,2,6,7}; var result = a.Intersect(b); foreach (var r in result) { Console.WriteLine(r); } Console.WriteLine("---------------"); result=a.Except(b); foreach (var r in result) { Console.WriteLine(r); } Console.WriteLine("---------------"); result = a.Union(b); foreach (var r in result) { Console.WriteLine(r); }
六、分区
Take()和Skip()常用来做分页操作。下面的demo演示分页。
int pageSize = 5; int pageCount = (int)Math.Ceiling(Student.GetAllStudents().Count()/(double)pageSize); for (int pageIndex = 0; pageIndex < pageCount; pageIndex++) { Console.WriteLine("page {0}",pageIndex); var result = (from s in Student.GetAllStudents().OrderBy(p => p.Age) select s).Skip(pageIndex * pageSize).Take(pageSize); foreach (var s in result) { Console.WriteLine("StuId:{0} Name:{1} Age:{2}", s.StuId, s.Name,s.Age); } }
七、限定符操作符
Any、All、Contains都是限定符操作符。Any是否有一个满足条件。ALL是所有元素都满足条件。Contains检查某个元素是否在集合中。都是返回布尔值。
bool anyFlag = Student.GetAllStudents().Any(p=>p.Name.Equals("xiaoming1") &&p.Age==25); bool allFlag = Student.GetAllStudents().Any(p =>p.Age == 25); Student s = new Student("001","xiaoming",25); bool containsFlag = Student.GetAllStudents().Contains(s); Console.WriteLine("Any:{0} All:{1} Contains:{2}",anyFlag,allFlag,containsFlag);
八、聚合函数
Linq还提供了Count()、Sum()、Min()、Max()、Average()、Aggregate()一系列聚合函数。
时间: 2024-10-05 23:27:14