当前位置:网站首页>C# 一周入门高级编程之《C#-LINQ》Day Four
C# 一周入门高级编程之《C#-LINQ》Day Four
2022-08-11 03:46:00 【太阳风暴】
C# 一周入门高级编程之《C#-LINQ》
一、C# LINQ 是什么
C# 的LINQ语法类似数据库的查询方法,是一种数据集合的查询语法,LINQ可以直接查询数据库、泛型、以容器、以及xml文档。什么意思呐?我们对于一个集合可能操作就是通过循环,给出判断条件,然后满足条件的话就把这个元素添加到一个新的集合内返回就行啦,但是C#提供了另外的方法,就是用LINQ查询语法,用类似SQL语法对可查询对象进行筛选,就这个开发效率就很高了,而且这样的写法还很方便。
- 这篇文章主要是讲述 基本的 LINQ 对于泛型、容器的一些操作,
- 数据库部分、xml文档部分我暂时没有研究。分组以及连接部分暂未深入掌握
二、LINQ基础用法
初次尝试使用LINQ语法,下面有对几种集合类型进行查询例子,语法非常容易懂,可以工具可以好好利用。
使用LINQ有三个步骤。
- 指定数据源
- 创建查询语句
- 执行查询
如下面 代码例子所示
1. 对数组查询
如下对数组进行查询 大于100的元素
//创建数据源
int[] intList = {
32, 35, 43, 654, 76, 56, 57, 453, 3542, 46 };
//创建查询语句
IEnumerable<int> searchRes = from item in intList
where item >100
select item;
//执行查询
foreach(var item in searchRes)
{
Console.WriteLine(item);
}
//结果如下
654
453
3542
2. 对容器查询
如下对字符串列表查询
//创建数据源
List<string> stringList = new List<string>() {
"Helan","Linken", "Black", "Brownd", "Kindey" };
//创建查询语句
IEnumerable<string> stringSearchList = from item in stringList
where item.StartsWith("B") || item.StartsWith("K")
select item;
//执行查询
foreach(var item in stringSearchList)
{
Console.WriteLine(item);
}
//结果如下
Black
Brownd
Kindey
3. 对IEnumerable<>查询
//创建数据源
IEnumerable<double> doubeList = new double[]{
32.4, 3.25, 35.4, 3.65, 4.74, 3.575, 4.6675 };
//创建查询语句
var doubleSearchList = from item in doubeList
where item > 20.11
select item;
//执行查询
foreach(var item in doubleSearchList)
{
Console.WriteLine(item);
}
//结果如下
32.4
35.4
4. 非泛型(IEnumerable)如 ArrayList
对 这种非泛型查询需要指定 数据 对象的类型, 不然推断不出来是什么类型 ,因为其实泛型已经指明了数据项的类型
//创建数据源
ArrayList arrayList = new ArrayList() {
42, 34, 43, 434, -4, 354, 65, 754, 7, -43, 764, 2, };
//创建查询语句
var arrayListRes = from int item in arrayList
where item <= 0
select item;
//执行查询
foreach(var item in arrayListRes)
{
Console.WriteLine(item);
}
//查询结果
-4
-43
三、获取数据源
所谓获取数据源,其实在上面例子中已经说明很清晰啦,数据源其实就是一个数据集合,我们需要指定一个集合作为我们查询的基础条件,在 LINQ 查询中,第一步是指定数据源。 在 LINQ 查询中,先使用 from 子句引入数据源以及数据项。
- 如下:
//创建数据源
IEnumerable<double> doubeList = new double[]{
32.4, 3.25, 35.4, 3.65, 4.74, 3.575, 4.6675 };
//from 则是引入数据源 以及指定数据项
var doubleSearchList = from item in doubeList
....
- 查询表达式中不会真正发生迭代
- 当执行查询时,才会迭代 也即是 使用了 foreach 查询关键词时
四、选择对象
选择对象其实就是 select item,select 子句生成查询结果并指定每个返回的元素的“形状”或类型。 例如,可以指定结果包含的是整个 Customer 对象、仅一个成员、成员的子集,还是某个基于计算或新对象创建的完全不同的结果类型。 这就牛逼了,意思就是说 满足条件的 数据项 可以对其进行一定的操作再返回
- 当 select 子句生成除源元素副本以外的内容时,该操作称为投影。(只要不是 from item in xxx select item) 结果只要不是原来的副本就是投影
示例:选择以 B ,K 开头的字符串并全部转为大写
List<string> stringList = new List<string>() {
"Helan","Linken", "Black", "Brownd", "Kindey" };
IEnumerable<string> stringSearchList = from item in stringList
where item.StartsWith("B") || item.StartsWith("K")
select item.ToUpper();
foreach(var item in stringSearchList)
{
Console.WriteLine(item);
}
//结果
BLACK
BROWND
KINDEY
五、筛选
筛选其实就是使用一定的条件过滤出我们想要的结果,使用的关键字就是 where ,在上面的很多例子里都使用了where 作为筛选条件。
- 筛选器查询 仅返回表达式为 true 的元素。
- 筛选器实际指定要从源序列排除哪些元素。
那就知道了 where 后面跟一个能计算出为 bool true 的表达式即可
能返回 true 的表达式就相对灵活了 可以是
- 逻辑运算符: !|| && > < == !=
- 函数式
var queryLondonCustomers = from cust in customers
where cust.City == "London"
select cust;
where cust.City == "London" && cust.Name == "Devon"
where cust.City == "London" || cust.City == "Paris"
一个查询表达式可以包含多个 where 子句,一个子句可以包含多个where子表达式。(不推荐这么用)
如下,结果都一样,第二个比较费脑子些
// 数据源
int[] numbers = {
5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
// 查询表达式
var queryLowNums2 =
from num in numbers
where num < 5 && num % 2 == 0
select num;
// 执行筛选
foreach (var s in queryLowNums2)
{
Console.Write(s.ToString() + " ");
}
Console.WriteLine();
// 查询表达式
var queryLowNums3 =
from num in numbers
where num < 5
where num % 2 == 0
select num;
// 执行筛选
foreach (var s in queryLowNums3)
{
Console.Write(s.ToString() + " ");
}
//结果
// 4 2 0
// 4 2 0
- where 子句是一种筛选机制。 除了不能是第一个或最后一个位置外,它几乎可以放在查询表达式中的任何位置。 where 子句可以出现在 group 子句的前面或后面,具体取决于时必须在对源元素进行分组之前还是之后来筛选源元素。
六、排序
在查询表达式中,orderby 子句可对满足条件的序列或子序列(组)以升序或降序排序。 同时我们可以使用一个个或多个次级排序操作,可以指定多个键来排序。 元素类型的默认比较器执行排序。 默认排序顺序为升序。 还可以指定自定义比较器。
排序的方式有两种:一种升序,一种降序
- 升序:从小到大
- 降序:从大到小
- 数值类:按照 大小排列
- 字符串:按照 首字母 A-Z 或者 Z-A排列
最简单的使用用法之一如下:
// 待查询类的属性
public class Customer
{
public string Name{
get;set;}
public string City{
get;set;}
}
//数据源
List <Customer> customers = new List <Customer>(){
/*一系列初始化*/};
//查询London 城市的Name, 按照升序排列A-Z排序
//若 对结果进行从 Z 到 A 的逆序排序,使用 orderby descending即可
var queryLondonCustomers3 =
from cust in customers
where cust.City == "London"
orderby cust.Name ascending
select cust;
简单排序查询-示例
// 创建数据源
string[] fruits = {
"cherry", "apple", "blueberry" };
// 查询语句-升序
IEnumerable<string> sortAscendingQuery =
from fruit in fruits
orderby fruit //默认升序
select fruit;
// 查询语句-降序
IEnumerable<string> sortDescendingQuery =
from w in fruits
orderby w descending
select w;
// 执行查询
Console.WriteLine("Ascending:");
foreach (string s in sortAscendingQuery)
{
Console.WriteLine(s);
}
// 执行查询
Console.WriteLine(Environment.NewLine + "Descending:");
foreach (string s in sortDescendingQuery)
{
Console.WriteLine(s);
}
//结果
Ascending:
apple
blueberry
cherry
Descending:
cherry
blueberry
apple
除了可以直接排序一次,还可以使用次要排序,次要排序的意思其实就是说,在第一轮排序内部的肯定在同级下面有很多相同的数据,我们还可以对其进一步这个已排序组内再进行一次排序。下面看官网的示例就知道啦
// 数据源的数据项的具体描述
public class Student
{
public string First {
get; set; }
public string Last {
get; set; }
public int ID {
get; set; }
}
//产生一个数据集合
public static List<Student> GetStudents()
{
List<Student> students = new List<Student>
{
new Student {
First="Svetlana", Last="Omelchenko", ID=111},
new Student {
First="Claire", Last="O'Donnell", ID=112},
new Student {
First="Sven", Last="Mortensen", ID=113},
new Student {
First="Cesar", Last="Garcia", ID=114},
new Student {
First="Debra", Last="Garcia", ID=115}
};
return students;
}
//主函数执行
static void Main(string[] args)
{
// 产生数据源
List<Student> students = GetStudents();
// 创建查询
IEnumerable<Student> sortedStudents =
from student in students
orderby student.Last ascending, student.First ascending
//先按照 Last 升序排,在升序组内再安装 First 排序即可
select student;
// 执行查询
Console.WriteLine("sortedStudents:");
foreach (Student student in sortedStudents)
{
Console.WriteLine(student.Last + " " + student.First);
}
//这里涉及到分组的知识,分组的基本条件是要排序后再分组,
var sortedGroups =
from student in students
orderby student.Last, student.First //忽略了 ascending 关键词
group student by student.Last[0] into newGroup //分组按照 Last首字母,分组后把分组结果塞到newGroup
orderby newGroup.Key //分组的集合再排序一次
select newGroup;
// 执行查询
Console.WriteLine(Environment.NewLine + "sortedGroups:");
foreach (var studentGroup in sortedGroups)
{
Console.WriteLine(studentGroup.Key);
foreach (var student in studentGroup)
{
Console.WriteLine(" {0}, {1}", student.Last, student.First);
}
}
}
/* Output: sortedStudents: Garcia Cesar Garcia Debra Mortensen Sven O'Donnell Claire Omelchenko Svetlana sortedGroups: G Garcia, Cesar Garcia, Debra M Mortensen, Sven O O'Donnell, Claire Omelchenko, Svetlana */
七、分组
分组和数据的基本一致,要使用分组的特性就需要使用group 关键字, 在分组语句中 毫无疑问需要我们指定分组的方式,这个方式一般通过统一的类型,就是键 key。分组的结果就是一个键值对, 例如,我们可指定按 City 对结果进行分组,使来自 London 或 Paris 的所有客户位于单独的组内。
- 使用 group 子句结束查询时,结果将以列表的形式列出。 列表中的每个元素都是具有 Key 成员的对象,列表中的元素根据该键被分组。 在循环访问生成组序列的查询时,必须使用嵌套 foreach 循环。 外层循环循环访问每个组,内层循环循环访问每个组的成员。
// queryCustomersByCity 是这种类型: IEnumerable<IGrouping<string, Customer>>
var queryCustomersByCity =
from cust in customers
group cust by cust.City;
// customerGroup 类型结构 IGrouping<string, Customer>
foreach (var customerGroup in queryCustomersByCity)
{
Console.WriteLine(customerGroup.Key);
foreach (Customer customer in customerGroup)
{
Console.WriteLine(" {0}", customer.Name);
}
}
边栏推荐
- Interchangeability and Measurement Techniques - Tolerance Principles and Selection Methods
- Detailed explanation of VIT source code
- 高校就业管理系统设计与实现
- Paper Accuracy - 2017 CVPR "High-Resolution Image Inpainting using Multi-Scale Neural Patch Synthesis"
- 云平台下ESB产品开发步骤说明
- The most unlucky and the luckiest
- Leetcode 108. 将有序数组转换为二叉搜索树
- 电商项目——商城限时秒杀功能系统
- CTO说MySQL单表行数不要超过2000w,为啥?
- 树莓派入门(5)系统备份
猜你喜欢
【FPGA】day21-移动平均滤波器
"Life Is Like First Seen" is ill-fated, full of characters, and the contrast of Zhu Yawen's characters is too surprising
Environment configuration of ESP32 (arduino arduino2.0 VScode platform which is easy to use?)
AI+Medical: Using Neural Networks for Medical Image Recognition and Analysis
移动端地图开发选择哪家?
The last update time of the tables queried by the two nodes of the rac standby database is inconsistent
【FPGA】SDRAM
互换性与测量技术-公差原则与选用方法
Redis老了吗?Redis与Dragonfly性能比较
DNS separation resolution and intelligent resolution
随机推荐
什么是三方支付?
Leetcode 108. 将有序数组转换为二叉搜索树
机器学习中什么是集成学习?
【FPGA】设计思路——I2C协议
"Life Is Like First Seen" is ill-fated, full of characters, and the contrast of Zhu Yawen's characters is too surprising
LeetCode刷题第16天之《239滑动窗口最大值》
oracle的基数会影响到查询速度吗?
How does MSP430 download programs to the board?(IAR MSPFET CCS)
轮转数组问题:如何实现数组“整体逆序,内部有序”?“三步转换法”妙转数组
Enter the starting position, the ending position intercepts the linked list
pathman_config、pathman_config_params 删除后,如何重建?
Element's BFC attribute
Environment configuration of ESP32 (arduino arduino2.0 VScode platform which is easy to use?)
The impact of programmatic trading and subjective trading on the profit curve!
阿里低代码框架 lowcode-engine 之自定义物料篇
【FPGA】day21-移动平均滤波器
Differences and connections between distributed and clustered
输入起始位置,终止位置截取链表
我的 archinstall 使用手册
浮点数在内存中的存储方式