C#学习(十二)——Linq

一、Linq

Language-Integrated Query 语言集成查询
对内存中数据、关系数据和XML数据执行的查询进行检查

例如,在不使用Linq语法时,想要实现查看C盘windows文件夹下最大的前五个文件

class Program
{static void Main(string[] args){//实现文件排序功能string path = @"c:\windows";ShowLargestFiles(path);Console.Read();}private static void ShowLargestFiles(string path){DirectoryInfo directory = new DirectoryInfo(path);FileInfo[] files = directory.GetFiles();Array.Sort(files, new FileInfoCompare());//输出最大的前五个文件for(int i = 0; i < 5; i++){var f = files[i];Console.WriteLine($"{f.Name,-20} : {f.Length,10:N}");}}
}class FileInfoCompare : IComparer<FileInfo>
{public int Compare(FileInfo x, FileInfo y){return y.Length.CompareTo(x.Length);}
}

那么使用Linq语法后的代码实现
Linq就是将命令式语法转变成声明式语法

  • [ 命令式是过程导向的,而声明式则是结果导向的 ]

声明式语言更加友好,可以帮助我们脱离细节,而更专注于业务操作和数据之间的逻辑关系
命令式更适合处理对象关系和逻辑过程,而声明式更适合处理数据关系

class Program
{static void Main(string[] args){//实现文件排序功能string path = @"c:\windows";ShowLargestFilesWithLinq(path);Console.Read();}private static void ShowLargestFilesWithLinq(string path){var query = from file in new DirectoryInfo(path).GetFiles()orderby file.Length descendingselect file;foreach (var f in query.Take(5)){Console.WriteLine($"{f.Name,-20} : {f.Length,10:N}");}}
}

关于query也可以通过对象的链式表达来写

private static void ShowLargestFilesWithLinq(string path)
{//var query = from file in new DirectoryInfo(path).GetFiles()//            orderby file.Length descending//            select file;var query = new DirectoryInfo(path).GetFiles().OrderByDescending(f => f.Length).Take(5);foreach (var f in query){Console.WriteLine($"{f.Name,-20} : {f.Length,10:N}");}
}

二、Lambda表达式

比如要获取名称以A为开头的所有文件

IEnumerable<string> file = files.Where(StartWithA);
public bool StartWithA(string name)
{return name.StartsWith("a");
}        

使用匿名方法来实现,以下为通过内联方法incline()来实现

IEnumerable<string> file = files.Where(delegate(string s){return s.StartWithA("a")}

使用Lambda表达式来实现

 var query = new DirectoryInfo(path).GetFiles().OrderByDescending(f => f.Length).Where(f => f.Name.StartsWith("a")).Take(5);

代码更加清晰简洁

三、Linq查询语法

Linq语句最终的决定,数据类型的读取是由select所决定的

class Program
{static void Main(string[] args){var customers = new List<Customer>{new Customer(1, "Jason", "广州"),new Customer(2, "Janny", "北京"),new Customer(3, "Pral", "上海"),new Customer(4, "Anna", "广州"),new Customer(5, "Angie", "深圳"),new Customer(6, "Bob", "武汉"),new Customer(7, "Tony", "深圳")};//var query = from c in customers//            where c.Address == "广州"//            orderby c.Name//            select c;//等效对象语法结构var query = customers.Where(c => c.Address == "广州").OrderBy(c => c.Name);foreach (var c in query){Console.WriteLine($"客户:{c.Id}, {c.Name}, {c.Address}");}Console.Read();}
}
public class Customer
{public Customer(int id, string name, string address){Id = id;Name = name;Address = address;}public int Id { get; set; }public string Name { get; set; }public string Address { get; set; }
}

四、Linq原理剖析

我们通过手写MyWhere语句来实现一个与where语句相同的效果

class Program
{static void Main(string[] args){var customers = new List<Customer>{new Customer(1, "Jason", "广州"),new Customer(2, "Janny", "北京"),new Customer(3, "Pral", "上海"),new Customer(4, "Anna", "广州"),new Customer(5, "Angie", "深圳"),new Customer(6, "Bob", "武汉"),new Customer(7, "Tony", "深圳")};var query = customers.Mywhere(c => c.Address == "广州").OrderBy(c => c.Name);foreach (var c in query){Console.WriteLine($"客户:{c.Id}, {c.Name}, {c.Address}");}Console.Read();}
}
public class Customer
{public Customer(int id, string name, string address){Id = id;Name = name;Address = address;}public int Id { get; set; }public string Name { get; set; }public string Address { get; set; }
}

MyList.cs

 public static class MyLink{public static IEnumerable<T> Mywhere<T>(this IEnumerable<T> source, Func<T, bool> predicate)//如果source数据符合委托方法predicate要求,就返回数据,否则不返回任何数据{var result = new List<T>();foreach ( var item in source){if ( predicate(item)){result.Add(item);}}return result;}}

不过Where语句的内部要远比我们实现的这个MyWhere要更复杂,其可以实现一个延迟执行的效果。从底层逻辑来说,where语句正是利用了yield return来实现数据的延迟加载,运行效率是非常高的。那么下面在利用yield return,对MyWhere进行更新。

public static class MyLink
{public static IEnumerable<T> Mywhere<T>(this IEnumerable<T> source, Func<T, bool> predicate)//如果source数据符合委托方法predicate要求,就返回数据,否则不返回任何数据{var result = new List<T>();foreach ( var item in source){if ( predicate(item)){yield return item;}}}
}

虽然我们在逻辑上没有看到大的变化,但是运行效率是有极大提升的!

五、使用Linq读取并过滤CSV数据

CSV数据已分享,放入项目中,文件属性调整为如果较新则复制

 class Program{static void Main(String[] args){List<Car> cars = ProcessCars("fuel.csv");//var query = cars//    .OrderByDescending(c => c.Combined)//    .ThenByDescending(c => c.Model);//输出油耗排名前十的车.....绝不可以连续使用OrderBy//声明式语句更加简单var query = from car in carsorderby car.Combined descending, car.Model descendingselect car;foreach (var car in query.Take(10)){Console.WriteLine($"{car.Model} {car.Combined}");}//想要提取油耗最多的车var query2 = (from car in carsorderby car.Combined descending, car.Model descendingselect car)//.First();列表为空时,first会报错,但是FirstOrDefault不会.FirstOrDefault();Console.WriteLine($"{query2.Model} {query2.Combined}");Console.Read();}private static List<Car> ProcessCars(string v){var result = File.ReadAllLines(v).Skip(1).Where(l => l.Length > 1).Select(line =>{var columes = line.Split(",");return new Car{Year = columes[0],Manufacturer = columes[1],Model = columes[2],Displacement = double.Parse(columes[3]),CylindersCount = int.Parse(columes[4]),City = int.Parse(columes[5]),Highway = int.Parse(columes[6]),Combined = int.Parse(columes[7])};});return result.ToList();}}

Car.cs

public class Car
{public string Year { get; set; }public string Manufacturer { get; set; }public string Model { get; set; }public double Displacement { get; set; }public int CylindersCount { get; set; }public int City { get; set; }public int Highway { get; set; }public int Combined { get; set; }
}

在读取获得最多耗油量车时,之所以不使用Take(1),是因为first或者FirstOrDefault方法,会在提取数据时,同时展开集合,可以为接下来的开发带来极大便利。

六、数据量化Any、All、Contains

Any,判断是否符合某一条件,返回bool值

//Any查询是否存在大众汽车
var query3 = cars.Any(car => car.Manufacturer == "Volkswagen");
Console.WriteLine(query3);
if (query3)
{Console.WriteLine("有大众");
}
else
{Console.WriteLine("无大众");
}
//判断集合是否为空
var isCarsEmpty = cars.Any();

Contains方法,参数接受的不是lambda方法,而是实例化对象。

//Contains
var isReal = cars.Contains(query2);

All方法,与any完全相反,查询是否完全符合某一条件

//All
var query4 = cars.All(car => car.Manufacturer == "Volkswagen");
Console.WriteLine(query3);
if (query4)
{Console.WriteLine("全是大众");
}
else
{Console.WriteLine("并不是全是大众");
}

七、数据投影与SelectMany

在上文中,使用select语句可以对数据进行塑性,数据类型发生了变化,对数据塑性的过程叫做数据投影
下面我们对select语句自己进行重写

private static List<Car> ProcessCars(string v)
{var result = File.ReadAllLines(v).Skip(1).Where(l => l.Length > 1).ToCar()return result.ToList();
}public static class CarExtension
{public static IEnumerable<Car> ToCar(this IEnumerable<string> source){foreach (var line in source){var columes = line.Split(",");yield return new Car{Year = columes[0],Manufacturer = columes[1],Model = columes[2],Displacement = double.Parse(columes[3]),CylindersCount = int.Parse(columes[4]),City = int.Parse(columes[5]),Highway = int.Parse(columes[6]),Combined = int.Parse(columes[7])};}}
}

在上面想要得到耗油量最多的车时,我们只需要得到Model和Combined,任何其他的数据都是冗余数据,因此可以使用select来去除多余数据

//想要提取油耗最多的车
var query2 = (from car in carsorderby car.Combined descending, car.Model descendingselect new{Model = car.Model,Combined = car.Combined}).FirstOrDefault();

SelectMany()–>展开嵌套集合,并且提取子集合中的所有数据

//输出每一辆车的型号
var query5 = cars.SelectMany(c => c.Model);
foreach (var car in query5)
{Console.WriteLine(car);
}

八、数据连接join

Linq中的join对应sql中的inner join内链接,任何数据只要在任意一个数据源中缺失,就会忽略整个数据的输出

以下对多数据源,两个CSV文件的数据进行处理
Program.cs

class Program
{static void Main(string[] args){List<Car> cars = ProcessCars("fuel.csv");List<Manufacturer> manufacturers = ProcessManufacturers("manufacturers.csv");var query = (from car in carsjoin manufacturer in manufacturers on car.Manufacturer equals manufacturer.Nameorderby car.Combined descending, car.Model descendingselect new{Manufacturer = car.Manufacturer,Model = car.Model,Combined = car.Combined,Headquarters = manufacturer.Headquarters,Phone = manufacturer.Phone}).Take(10);foreach (var c in query){Console.WriteLine($"{c.Manufacturer} {c.Model} {c.Combined} {c.Headquarters} {c.Phone}");}Console.WriteLine("\n");//使用对象调用方式实现var query2 = cars.Join(manufacturers, (c) => c.Manufacturer, (m) => m.Name, (c, m) => new{Car = c,Manufacturer = m}).OrderByDescending(joinData => joinData.Car.Combined).ThenBy(joinData => joinData.Car.Model).Select(joinData => new{Manufacturer = joinData.Car.Manufacturer,Model = joinData.Car.Model,Combined = joinData.Car.Combined,Headquarters = joinData.Manufacturer.Headquarters,Phone = joinData.Manufacturer.Phone}).Take(10);foreach (var c in query2){Console.WriteLine($"{c.Manufacturer} {c.Model} {c.Combined} {c.Headquarters} {c.Phone}");}Console.Read();}private static List<Car> ProcessCars(string v){var result = File.ReadAllLines(v).Skip(1).Where(l => l.Length > 1).ToCar()//.Select(line =>//{//    var columns = line.Split(",");//    return new Car//    {//        Year = columns[0],//        Manufacturer = columns[1],//        Model = columns[2],//        Displacement = double.Parse(columns[3]),//        CylindersCount = int.Parse(columns[4]),//        City = int.Parse(columns[5]),//        Highway = int.Parse(columns[6]),//        Combined = int.Parse(columns[7])//    };//});return result.ToList();}private static List<Manufacturer> ProcessManufacturers(string path){var query = File.ReadAllLines(path).Where(l => l.Length > 1).Select(l =>{var columns = l.Split(',');return new Manufacturer{Name = columns[0],Headquarters = columns[1],Phone = columns[2]};});return query.ToList();}
}public static class CarExtensions
{public static IEnumerable<Car> ToCar(this IEnumerable<string> source){foreach (var line in source){var columns = line.Split(",");yield return new Car{Year = columns[0],Manufacturer = columns[1],Model = columns[2],Displacement = double.Parse(columns[3]),CylindersCount = int.Parse(columns[4]),City = int.Parse(columns[5]),Highway = int.Parse(columns[6]),Combined = int.Parse(columns[7])};}}
}

Car.cs

public class Car
{public string Year { get; set; }public string Manufacturer { get; set; }public string Model { get; set; }public double Displacement { get; set; }public int CylindersCount { get; set; }public int City { get; set; }public int Highway { get; set; }public int Combined { get; set; }
}

Manufacturer.cs

public class Manufacturer
{public string Name { get; set; }public string Headquarters { get; set; }public string Phone { get; set; }
}

九、数据分组group

例如想得到所有生产商排名油耗前两名的汽车型号

//想得到所有生产商排名油耗前两名的汽车型号
var query3 = from car in carsgroup car by car.Manufacturer into manufacturerGrouporderby manufacturerGroup.Key descendingselect manufacturerGroup;foreach (var group in query3)
{Console.WriteLine($"{group.Key}{group.Count()} 辆汽车 \n 油耗前两名为:" );foreach(var car  in group.OrderByDescending(c => c.Combined).Take(2)){Console.WriteLine($"\t{car.Model} 油耗为:{car.Combined}");}
}//使用对象化方法实现以上语句
var query4 = cars.GroupBy(c => c.Manufacturer).OrderByDescending(g => g.Key);
foreach (var group in query4)
{Console.WriteLine($"{group.Key}{group.Count()} 辆汽车 \n 油耗前两名为:");foreach (var car in group.OrderByDescending(c => c.Combined).Take(2)){Console.WriteLine($"\t{car.Model} 油耗为:{car.Combined}");}
}

十、数据分组连接 group join

可以对多个数据源同时进行分组

想得到所有生产商排名油耗前两名的汽车型号,同时想得到总部地址以及联系电话

//想得到所有生产商排名油耗前两名的汽车型号,同时想得到总部地址以及联系电话
var query5 = from manufacturer in manufacturersjoin car in cars on manufacturer.Name equals car.Manufacturer into carGrouporderby manufacturer.Name descendingselect new{Manufacturer = manufacturer,Cars = carGroup};
foreach (var group in query5)
{Console.WriteLine($"{group.Manufacturer.Name} {group.Manufacturer.Headquarters} {group.Manufacturer.Phone}");foreach (var car in group.Cars.OrderByDescending(c => c.Combined).Take(2)){Console.WriteLine($"\t{car.Model} 油耗为:{car.Combined}");}
}//使用对象化方法实现以上语句
var query6 = manufacturers.GroupJoin(cars, m => m.Name, c => c.Manufacturer, (m, carGroup) => new
{Manufacturer = m,Cars = carGroup
}).OrderByDescending(m => m.Manufacturer.Name);foreach (var group in query6)
{Console.WriteLine($"{group.Manufacturer.Name} {group.Manufacturer.Headquarters} {group.Manufacturer.Phone}");foreach (var car in group.Cars.OrderByDescending(c => c.Combined).Take(2)){Console.WriteLine($"\t{car.Model} 油耗为:{car.Combined}");}
}

十一、数据聚合

Linq可以在处理分组数据的过程中进行聚合运算

例如实现找出每个品牌的平均油耗,最高油耗,最低油耗

//找出每个品牌的平均油耗,最高油耗,最低油耗
var query7 = from car in carsgroup car by car.Manufacturer into carGroupselect new{Manufacture = carGroup.Key,Avg = carGroup.Average(c => c.Combined),Max = carGroup.Max(c => c.Combined),Min = carGroup.Min(c => c.Combined)} into tempGrouporderby tempGroup.Avg descendingselect tempGroup;foreach (var group in query7)
{Console.WriteLine($"{group.Manufacture} 油耗情况");Console.WriteLine($"\t 最高:{group.Max}");Console.WriteLine($"\t 最低:{group.Min}");Console.WriteLine($"\t 平均:{group.Avg}");               
}
//使用对象化方法实现以上语句
var query8 = cars.GroupBy(c => c.Manufacturer, (c, carGroup) => new
{Manufacture = c,Avg = carGroup.Average(c => c.Combined),Max = carGroup.Max(c => c.Combined),Min = carGroup.Min(c => c.Combined)}).OrderByDescending(c => c.Avg);foreach (var group in query8)
{Console.WriteLine($"{group.Manufacture} 油耗情况");Console.WriteLine($"\t 最高:{group.Max}");Console.WriteLine($"\t 最低:{group.Min}");Console.WriteLine($"\t 平均:{group.Avg}");
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/668240.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【力扣 51】N 皇后(回溯+剪枝+深度优先搜索)

按照国际象棋的规则&#xff0c;皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题 研究的是如何将 n 个皇后放置在 nn 的棋盘上&#xff0c;并且使皇后彼此之间不能相互攻击。 给你一个整数 n &#xff0c;返回所有不同的 n 皇后问题 的解决方案。 每一种…

【数据结构与算法】(3)基础数据结构 之 链表 单向链表、双向链表、循环链表详细示例讲解

目录 2.2 链表1) 概述2) 单向链表3) 单向链表&#xff08;带哨兵&#xff09;4) 双向链表&#xff08;带哨兵&#xff09;5) 环形链表&#xff08;带哨兵&#xff09; 2.2 链表 1) 概述 定义 在计算机科学中&#xff0c;链表是数据元素的线性集合&#xff0c;其每个元素都指…

Rust 本地文档的使用:rustup doc

Rust 是一种系统级编程语言&#xff0c;以其安全性、速度和内存控制能力而闻名。为了方便开发者更好地了解并利用 Rust 标准库和工具链中的功能&#xff0c;Rust 提供了一种内置的文档浏览方式——通过 rustup doc 命令。 安装 rustup 在查阅 Rust 文档之前&#xff0c;确保你…

蓝桥杯刷题--python-1

0门牌制作 - 蓝桥云课 (lanqiao.cn) import os import sys # 请在此输入您的代码 res0 for i in range (1,2021): xstr(i) resx.count(2) print(res) 0卡片 - 蓝桥云课 (lanqiao.cn) import os import sys # 请在此输入您的代码 res_10 for i in range(1,99999999999999999): r…

platfrom tree架构下实现3-Wire驱动(DS1302)

目录 概述 1 认识DS1302 1.1 DS1302 硬件电路 1.2 操作DS1302 1.3 注意要点 2 IO引脚位置 3 添加驱动节点 3.1 更新内核.dts 3.2 更新板卡.dtb 4 驱动程序实现 4.1 编写驱动程序 4.2 编写驱动程序的Makefile 4.3 安装驱动程序 5 验证驱动程序 5.1 编写测试程序…

何时以及如何选择制动电阻

制动电阻的选择是优化变频器应用的关键因素 制动电阻器在变频器中是如何工作的&#xff1f; 制动电阻器在 VFD 应用中的工作原理是将电机减速到驱动器设定的精确速度。它们对于电机的快速减速特别有用。制动电阻还可以将任何多余的能量馈入 VFD&#xff0c;以提升直流母线上的…

Electron实战(二):将Node.js和UI能力(app/BrowserWindow/dialog)等注入html

文章目录 设置webPreferences参数安装electron/remotemain进程中初始化html中使用dialog踩坑参考文档 上一篇&#xff1a;Electron实战(一)&#xff1a;环境搭建/Hello World/打包exe 设置webPreferences参数 为了能够在html/js中访问Node.js提供fs等模块&#xff0c;需要在n…

新概念英语第二册(54)

【New words and expressions】生词和短语&#xff08;14&#xff09; sticky adj. 粘的 finger n. 手指 pie n. 馅饼 mix v. 混合&#xff0c;拌和 pastr…

踩坑实录(First Day)

2023 年一整年感觉我的进步都很小&#xff0c;所以自 2024 年起&#xff0c;我将专门开设专栏记录自己在工作期间踩过的所有坑&#xff0c;一来是为了有个记录&#xff0c;自己不会再踩&#xff0c;而来也是为了跟大家做一个分享&#xff0c;与大家进行讨论&#xff0c;提升自己…

力扣宝石补给

欢迎各位勇者来到力扣新手村&#xff0c;在开始试炼之前&#xff0c;请各位勇者先进行「宝石补给」。 每位勇者初始都拥有一些能量宝石&#xff0c; gem[i] 表示第 i 位勇者的宝石数量。现在这些勇者们进行了一系列的赠送&#xff0c;operations[j] [x, y] 表示在第 j 次的赠送…

QT 范例阅读:系统托盘 The System Tray Icon example

main.cpp QApplication app(argc, argv);//判断系统是否支持 系统托盘功能if (!QSystemTrayIcon::isSystemTrayAvailable()) {QMessageBox::critical(0, QObject::tr("Systray"),QObject::tr("I couldnt detect any system tray ""on this system.&qu…

利用jmeter完成简单的压力测试

Jmeter是一个非常好用的压力测试工具。Jmeter用来做轻量级的压力测试&#xff0c;非常合适&#xff0c;只需要十几分钟&#xff0c;就能把压力测试需要的脚本写好。 1、什么是压力测试 顾名思义&#xff1a;压力测试&#xff0c;就是 被测试的系统&#xff0c;在一定的访问压…

下载、安装Jenkins

进入官网 下载Jenkins https://www.jenkins.io 直接点击Download 一般是下长期支持版 因为它是java写的&#xff0c;你要运行它&#xff08;Jenkins.war&#xff09;肯定要有java环境 有两种方式去运行它&#xff0c;一种是下载Tomcat&#xff08;是很经典的java容器或者jav…

代码随想录day16 Java版 二叉树部分

404.左叶子之和 感觉就是遍历&#xff0c;遇到叶子结点就累加&#xff0c;试了下居然过了 class Solution {int sum 0;public int sumOfLeftLeaves(TreeNode root) {add(root);return sum;}void add(TreeNode root){if (root null) return;if (root.left ! null &&…

linux编译ffmpeg动态库

1&#xff0c;获取源码&#xff1a;git clone https://git.ffmpeg.org/ffmpeg.git 2&#xff0c;创建编译目录&#xff0c;并编译、安装&#xff0c; cd ffmpeg mkdir build cd build ../configure --prefix~/ffmpeg --enable-shared --enable-debug1 //configure后需要使…

深入探索C++ Move语义:现代编程中的性能革命

1. 引言 介绍C中的Move语义 Move语义是C11中引入的一个重要特性&#xff0c;它为C编程语言带来了显著的性能改进。在这之前&#xff0c;C只支持拷贝语义&#xff0c;即通过拷贝构造函数和拷贝赋值操作符来复制对象。Move语义通过允许"移动"而非"拷贝"资源…

Git版本管理工具(基础):这一篇基本能满足Git基本的使用需求了!

文章目录 Git01-什么是Git作用 02-使用Git03-Git仓库创建 04-Git的三个区域三个区域 05-Git文件状态06-Git暂存区使用07-Git回退版本08-删除文件 Git 01-什么是Git 答&#xff1a;他是一个免费开源的&#xff0c;分布式代码版本控制系统&#xff0c;帮助开发团队维护代码 作用…

三、消除分心的事物(Eliminating Distractions)

External Improvements 外部改进 1.Eliminating Distractions 一、消除分心的事物 Distractions are the most obvious problem when it comes to focus, and they are often the easiest to fix. In particular, you want to find an environment for focus that minimizes b…

爬虫工作量由小到大的思维转变---<第四十五章 Scrapyd 关于gerapy遇到问题>

前言: 本章主要是解决一些gerapy遇到的问题,会持续更新这篇! 正文: 问题1: 1400 - build.py - gerapy.server.core.build - 78 - build - error occurred (1, [E:\\项目文件名\\venv\\Scripts\\python.exe, setup.py, clean, -a, bdist_uberegg, -d, C:\\Users\\Administrat…

网络安全面试题收集

1 Web篇 1.1 什么是SQL注入攻击&#xff1f;如何防止SQL注入攻击&#xff1f; SQL注入攻击是指攻击者通过向Web应用程序的输入框中插入恶意SQL语句来执行未经授权的操作。防止SQL注入攻击的方法包括使用参数化查询和输入验证&#xff0c;以及避免使用动态SQL语句。 1.2 什么…