02020208 .NET Core重难点知识08-常用扩展方法、排序、限制结果集获取部分数据
02020208 .NET Core重难点知识08
1. 常用扩展方法1(视频Part2-17)
- 本章节笔记中,需要如下元数据
using System;
using System.Collections.Generic;
using System.Linq;
namespace Demo02
{
class Employee
{
public long Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public bool Gender { get; set; }
public int Salay { get; set; }
public override string ToString()
{
return $"Id = {Id}, Name = {Name}, Age = {Age}, Gender = {Gender}, Salary = {Salay}";
}
}
class Program
{
static void Main(string[] args)
{
List<Employee> list = new List<Employee>();
list.Add(new Employee { Id = 1, Name = "jerry", Age = 28, Gender = true, Salay = 5000 });
list.Add(new Employee { Id = 2, Name = "jim", Age = 33, Gender = true, Salay = 3000 });
list.Add(new Employee { Id = 3, Name = "lily", Age = 35, Gender = false, Salay = 9000 });
list.Add(new Employee { Id = 4, Name = "lucy", Age = 16, Gender = false, Salay = 2000 });
list.Add(new Employee { Id = 5, Name = "kimi", Age = 25, Gender = true, Salay = 1000 });
list.Add(new Employee { Id = 6, Name = "nancy", Age = 36, Gender = false, Salay = 8000 });
list.Add(new Employee { Id = 7, Name = "zack", Age = 35, Gender = true, Salay = 8500 });
list.Add(new Employee { Id = 8, Name = "jack", Age = 33, Gender = true, Salay = 8000 });
}
}
}
1.1 LINQ中的扩展方法
- LINQ中提供了大量类似Where的扩展方法,简化数据处理。大部分都在System.Linq命名空间中。
- 这些扩展方法,大多数都是对IEnumerable
这个泛型接口的扩展。 - 数组、List、Dictionary、Set...等都是实现了IEnumerable接口的。因此它们都可以使用这些扩展方法的。
- 这些扩展方法,大多数都是对IEnumerable
1.2 Where方法
- 每一项数据都会经过predicate的测试,如果针对一个元素,predicate执行的返回值为true,那么这个元素就会放到返回值中。
- Where参数是一个Lambda表达式格式的匿名方法,方法的参数e表示当前判断的元素对象。参数的名字不一定非要叫做e,不过一般Lambda表达式中的变量名长度都不长。
static void Main(string[] args)
{
...
IEnumerable<Employee> items = list.Where(e => e.Age > 30);
foreach (Employee it in items)
{
Console.WriteLine(it);
}
Console.ReadLine();
}
1.3 Count方法
- Count方法用于获取数据条数。
static void Main(string[] args)
{
...
IEnumerable<Employee> items = list.Where(e => e.Age > 30);
Console.WriteLine(list.Count());
Console.WriteLine(items.Count());
Console.WriteLine(list.Count(e => e.Age > 20));
Console.WriteLine(list.Count(e => e.Age > 20 && e.Salay > 8000));
Console.ReadLine();
}
控制台输出:
8
5
7
2
1.4 Any方法
- Any方法用于判断是否至少有一条数据。
static void Main(string[] args)
{
...
IEnumerable<Employee> items = list.Where(e => e.Age > 30);
Console.WriteLine(list.Any());
Console.WriteLine(items.Any());
Console.WriteLine(list.Any(e => e.Age > 20 && e.Salay > 10000));
Console.ReadLine();
}
控制台输出:
True
True
False
说明:Count方法会将满足条件的数据都读出来,而Any只要触发了条件就可以。因此Any有可能比Count效率更高。
2. 常用扩展方法2(Part2-18)
- 获取一条数据(是否带参数的两种写法)
- Single → 有且只有一条满足要求的数据。
- SingleOrDefault → 最多只有一条满足要求的数据。
- First → 至少有一条,返回第一条数据。
- FirstOrDefault → 返回第一条或者默认值。
- Single → 有且只有一条满足要求的数据。
- 选择合适的方法,防御性编程。
2.1 Single方法
- 有且只有一条数据
// Single方法 → 有多条数据抛出异常
static void Main(string[] args)
{
...
Employee e1 = list.Single();
Console.WriteLine(e1);
Console.ReadLine();
}
异常信息:System.InvalidOperationException:“Sequence contains more than one element”
说明:Single表示有且只有一条数据,如果有多条数据,那么抛出异常。
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// Single方法 → 有且只有一条
static void Main(string[] args)
{
...
Console.WriteLine(list.Where(e => e.Name == "jerry").Single()); // @1
Console.ReadLine();
}
控制台输出:
Id = 1, Name = jerry, Age = 28, Gender = True, Salary = 5000
说明:在@1处(list.Where(e => e.Name == "jerry"),返回的是一个可迭代的数据,因此可以直接用Single()方法判断。
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// Single方法 → Where返回的是一个可迭代对象,可以直接用Single方法。
static void Main(string[] args)
{
...
Console.WriteLine(list.Where(e => e.Name == "Qinway").Single());
Console.ReadLine();
}
异常信息:System.InvalidOperationException:“Sequence contains no elements”
说明:Single方法,如果没有数据,也会抛出异常。
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// Single方法 → Lambda表达式作为参数
static void Main(string[] args)
{
Employee e2 = list.Single(e => e.Name == "jim");
Console.WriteLine(e2);
}
控制台输出:
Id = 2, Name = jim, Age = 33, Gender = True, Salary = 3000
2.2 SingleOrDefault方法
- 最多只有一条满足要求的数据,即可以有一条,也可以没有。
// Singel方法 → 最多一条,可以没有。
static void Main(string[] args)
{
Console.WriteLine(list.SingleOrDefault(e => e.Name == "jim")); // 有一条数据,返回。
Console.ReadLine();
}
控制台输出:
Id = 2, Name = jim, Age = 33, Gender = True, Salary = 3000
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// Single方法 → 如果一条数据都没有,对于值类型返回0,对于引用类型返回null。
static void Main(string[] args)
{
Employee e2 = list.SingleOrDefault(e => e.Name == "Qinway"); // 没有数据,对于引用类型,返回null。
Console.WriteLine(e2 == null); // → True
int[] nums = new int[] { 1, 3, 6 };
int e3 = nums.SingleOrDefault(e => e > 10); // 没有数据,对于值类型,返回0。
Console.WriteLine(e3); // → 0
Console.ReadLine();
}
控制台输出:
True
0
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// Single方法 → 有多条,抛出异常。
static void Main(string[] args)
{
Console.WriteLine(list.SingleOrDefault(e => e.Age > 20));
}
异常信息:System.InvalidOperationException:“Sequence contains more than one matching element”
2.3 First方法
- 至少有一条,返回第一条。
// First方法 → 有多条,返回第一条。
static void Main(string[] args)
{
Employee e2 = list.First(e => e.Age > 30);
Console.WriteLine(e2);
Console.ReadLine();
}
控制台输出:
Id = 2, Name = jim, Age = 33, Gender = True, Salary = 3000
说明:数据源从上往下数,遇到第一个就返回该数据。
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// First方法 → 如果一个都没有,抛出异常。
static void Main(string[] args)
{
Employee e2 = list.First(e => e.Age > 50); // 抛出异常。
Console.WriteLine(e2);
Console.ReadLine();
}
异常信息:System.InvalidOperationException:“Sequence contains no matching element”
2.4 FirstOrDefault
- 返回第一条或者默认值,可以没有,如果有返回第一个。
static void Main(string[] args)
{
Employee e1 = list.FirstOrDefault(e => e.Age > 30); // 有多条,返回第一条。
Console.WriteLine(e1);
Employee e2 = list.FirstOrDefault(e => e.Age > 50); // 一条没有,返回默认值。
Console.WriteLine(e2 == null); // → True
Console.ReadLine();
}
控制台输出:
Id = 2, Name = jim, Age = 33, Gender = True, Salary = 3000
True
2.5 总结
- 上述方法灵活运用,用合适的方法提前筛选并抛出异常。让异常提前暴露出来,及早发现,及早处理。有防御性编程的思维。
3. 排序
- Order方法 → 对数据正序排序。
- OrderByDescending方法 → 倒序排序。
list.OrderBy(e = e.Age);
说明:
1. 对于简单类型排序,可以用自身排序。
2. 特殊案例:按照最后一个字符排序,用Guide或者随机数进行随机排序。
3.1 正序、倒序、随机排序
// 对引用类型进行排序
static void Main(string[] args)
{
IEnumerable<Employee> items1 = list.OrderBy(e => e.Age);
foreach (Employee it in items1)
{
Console.WriteLine(it);
}
Console.WriteLine("**********************************");
IEnumerable<Employee> items2 = list.OrderByDescending(e => e.Age);
foreach (Employee it in items2)
{
Console.WriteLine(it);
}
Console.ReadLine();
}
控制台输出:
Id = 4, Name = lucy, Age = 16, Gender = False, Salary = 2000
Id = 5, Name = kimi, Age = 25, Gender = True, Salary = 1000
Id = 1, Name = jerry, Age = 28, Gender = True, Salary = 5000
Id = 2, Name = jim, Age = 33, Gender = True, Salary = 3000
Id = 8, Name = jack, Age = 33, Gender = True, Salary = 8000
Id = 3, Name = lily, Age = 35, Gender = False, Salary = 9000
Id = 7, Name = zack, Age = 35, Gender = True, Salary = 8500
Id = 6, Name = nancy, Age = 36, Gender = False, Salary = 8000
**********************************
Id = 6, Name = nancy, Age = 36, Gender = False, Salary = 8000
Id = 3, Name = lily, Age = 35, Gender = False, Salary = 9000
Id = 7, Name = zack, Age = 35, Gender = True, Salary = 8500
Id = 2, Name = jim, Age = 33, Gender = True, Salary = 3000
Id = 8, Name = jack, Age = 33, Gender = True, Salary = 8000
Id = 1, Name = jerry, Age = 28, Gender = True, Salary = 5000
Id = 5, Name = kimi, Age = 25, Gender = True, Salary = 1000
Id = 4, Name = lucy, Age = 16, Gender = False, Salary = 2000
说明:OrderBy返回的是IOrderedEnumerable<T>泛型接口,IOrderedEnumerable又继承自IEnumerable<T>泛型接口,因此可以用foreach遍历。
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// 对值类型进行排序
static void Main(string[] args)
{
int[] nums = new int[] { 10, 3, 1, 12, 6 };
IEnumerable<int> num1 = nums.OrderBy(e => e); // 注意这里Lambda表达式对应的匿名方法delegate (int e) {return e;},表示用自身排序
foreach (int n in num1)
{
Console.WriteLine(n);
}
Console.ReadLine();
}
控制台输出:
1
3
6
10
12
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// 使用NewGuid方法,进行随机排序。
static void Main(string[] args)
{
var items = list.OrderBy(e => Guid.NewGuid()); // NewGuid方法生成一个随机值,对这个随机值进行排序。
foreach (var it in items)
{
Console.WriteLine(it);
}
Console.ReadLine();
}
控制台输出:
Id = 3, Name = lily, Age = 35, Gender = False, Salary = 9000
Id = 2, Name = jim, Age = 33, Gender = True, Salary = 3000
Id = 8, Name = jack, Age = 33, Gender = True, Salary = 8000
Id = 1, Name = jerry, Age = 28, Gender = True, Salary = 5000
Id = 5, Name = kimi, Age = 25, Gender = True, Salary = 1000
Id = 4, Name = lucy, Age = 16, Gender = False, Salary = 2000
Id = 6, Name = nancy, Age = 36, Gender = False, Salary = 8000
Id = 7, Name = zack, Age = 35, Gender = True, Salary = 8500
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// 使用Random随机数排序
static void Main(string[] args)
{
Random rd = new Random();
var items = list.OrderBy(e => rd.Next()); // 通过随机数进行排序
foreach (var it in items)
{
Console.WriteLine(it);
}
Console.ReadLine();
}
控制台输出:
Id = 8, Name = jack, Age = 33, Gender = True, Salary = 8000
Id = 2, Name = jim, Age = 33, Gender = True, Salary = 3000
Id = 3, Name = lily, Age = 35, Gender = False, Salary = 9000
Id = 1, Name = jerry, Age = 28, Gender = True, Salary = 5000
Id = 6, Name = nancy, Age = 36, Gender = False, Salary = 8000
Id = 4, Name = lucy, Age = 16, Gender = False, Salary = 2000
Id = 5, Name = kimi, Age = 25, Gender = True, Salary = 1000
Id = 7, Name = zack, Age = 35, Gender = True, Salary = 8500
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// 根据Name最后一个字符进行排序
static void Main(string[] args)
{
var items = list.OrderBy(e => e.Name[e.Name.Length-1]);
foreach (var it in items)
{
Console.WriteLine(it);
}
Console.ReadLine();
}
控制台输出:
Id = 5, Name = kimi, Age = 25, Gender = True, Salary = 1000
Id = 7, Name = zack, Age = 35, Gender = True, Salary = 8500
Id = 8, Name = jack, Age = 33, Gender = True, Salary = 8000
Id = 2, Name = jim, Age = 33, Gender = True, Salary = 3000
Id = 1, Name = jerry, Age = 28, Gender = True, Salary = 5000
Id = 3, Name = lily, Age = 35, Gender = False, Salary = 9000
Id = 4, Name = lucy, Age = 16, Gender = False, Salary = 2000
Id = 6, Name = nancy, Age = 36, Gender = False, Salary = 8000
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
总结:排序表达式可以随意写。
3.2 多规则排序
- 可以在Order(),OrderByDecending()后继续写ThenBy()、ThenByDecending()。
// 示例:优先按照Age排序,如果Age相同在按照Salary排序。
list.OrderBy(e => e. Age).ThenByDecending(e => e.Salary)
注意:千万不要写成list.OrderBy(e => e. Age).OrderBy(e => e.Salary)
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// 按年龄从小到大排序,然后工资从大到小排序
static void Main(string[] args)
{
var items = list.OrderBy(e => e.Age).ThenByDescending(e => e.Salay);
foreach (var it in items)
{
Console.WriteLine(it);
}
Console.ReadLine();
}
控制台输出:
Id = 4, Name = lucy, Age = 16, Gender = False, Salary = 2000
Id = 5, Name = kimi, Age = 25, Gender = True, Salary = 1000
Id = 1, Name = jerry, Age = 28, Gender = True, Salary = 5000
Id = 8, Name = jack, Age = 33, Gender = True, Salary = 8000
Id = 2, Name = jim, Age = 33, Gender = True, Salary = 3000
Id = 3, Name = lily, Age = 35, Gender = False, Salary = 9000
Id = 7, Name = zack, Age = 35, Gender = True, Salary = 8500
Id = 6, Name = nancy, Age = 36, Gender = False, Salary = 8000
4 限制结果集,获取部分数据
- skip(n) → 跳过n条数据,Taken(n)获取n条数据。
var orderedItems = list.Skip(2).Taken(3); // 跳过2条,取3条。
说明:Skip()、Take()也可以单独使用。
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// 跳过2条,获取3条数据
static void Main(string[] args)
{
var orderedItems = list.Skip(2).Take(3);
foreach (var it in orderedItems)
{
Console.WriteLine(it);
}
Console.ReadLine();
}
控制台输出:
Id = 3, Name = lily, Age = 35, Gender = False, Salary = 9000
Id = 4, Name = lucy, Age = 16, Gender = False, Salary = 2000
Id = 5, Name = kimi, Age = 25, Gender = True, Salary = 1000
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// 跳过4条,取所有数据
static void Main(string[] args)
{
var orderedItems = list.Skip(4);
foreach (var it in orderedItems)
{
Console.WriteLine(it);
}
Console.ReadLine();
}
控制台输出:
Id = 5, Name = kimi, Age = 25, Gender = True, Salary = 1000
Id = 6, Name = nancy, Age = 36, Gender = False, Salary = 8000
Id = 7, Name = zack, Age = 35, Gender = True, Salary = 8500
Id = 8, Name = jack, Age = 33, Gender = True, Salary = 8000
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// 取4条数据,后面不要
static void Main(string[] args)
{
var orderedItems = list.Take(4);
foreach (var it in orderedItems)
{
Console.WriteLine(it);
}
Console.ReadLine();
}
控制台输出:
Id = 1, Name = jerry, Age = 28, Gender = True, Salary = 5000
Id = 2, Name = jim, Age = 33, Gender = True, Salary = 3000
Id = 3, Name = lily, Age = 35, Gender = False, Salary = 9000
Id = 4, Name = lucy, Age = 16, Gender = False, Salary = 2000
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// 添加过滤条件
static void Main(string[] args)
{
var orderedItems = list.Where(e => e.Age > 30).Take(2); // 先获取年龄大于30的,然后取2条。
foreach (var it in orderedItems)
{
Console.WriteLine(it);
}
Console.ReadLine();
}
控制台输出:
Id = 2, Name = jim, Age = 33, Gender = True, Salary = 3000
Id = 3, Name = lily, Age = 35, Gender = False, Salary = 9000
结尾
书籍:ASP.NET Core技术内幕与项目实战
视频:https://www.bilibili.com/video/BV1pK41137He
著:杨中科
ISBN:978-7-115-58657-5
版次:第1版
发行:人民邮电出版社
※敬请购买正版书籍,侵删请联系85863947@qq.com※
※本文章为看书或查阅资料而总结的笔记,仅供参考,如有错误请留言指正,谢谢!※