首页 > 编程语言 >[转]C# Linq

[转]C# Linq

时间:2022-12-16 12:55:41浏览次数:54  
标签:Count Console C# Linq WriteLine var new select

linq可以对多种数据源和对象进行查询,如数据库、数据集、XML文档、数组等。

通过对linq的使用,可以减少代码量并优化检索操作。

LINQ关键字

from 指定数据源和范围变量

where 根据布尔表达式(由逻辑与 或 等组成)从数据源中筛选元素

select 指定查询结果中的元素所具有的类型或表现形式

group 对对查询结果按照键值进行分组

into 提供一个标示符,它可以充当对 join group 或 select 子句结果的引用

orderby 对查询出的元素进行排序

join 按照两个指定匹配条件来联接俩个数据源

let 产生一个用于查询表达式中子表达式查询结果的范围变量

1. 组成

            // 1,获取数据源
            List<int> numbers = new List<int>() { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };

            // 2,创建查询
            var numQuery = from num in numbers
                           where num % 2 == 0
                           select num;

            // 3,执行查询
            foreach (var num in numQuery)
            {
                Console.WriteLine("{0,1}", num);
            }
         static void Main(string[] args)
        {
            //获取数据源
            string[] names = { "Alen", "Zhen", "Chen","Song", "Hel", "Ken", "Aln", "Zen", "Cen", "He", "Ke", };
            //创建查询
            var queryResults = from n in names where n.StartsWith("S") select n;
            Console.WriteLine("Names beginning with S:");
            //执行查询
            foreach (var item in queryResults)
            {
                Console.WriteLine(item);
            }
            Console.Write("Program finished,press Enter/Reurn to continue:");
            Console.ReadLine();
        }

2. 语句使用

            //1.用var关键字声明结果变量
            //2.指定数据源:from 子句
            //3.指定条件:where 子句
            //4.指定元素:select子句
            //5.完成:使用foreach循环
            string[] names = { "Alono", "Zheng", "Yuan", "Song", "Simle", "Hsieh", "Small", "She", "Sza", "Sam", "Fa", "Iyl" };
            var queryResults = from n in names
                               where n.StartsWith("S")
                               orderby n descending//按照最后一个字母排序 ordeby n.Substring(n.Length - 1)
                               select n;//查询语法
            var queryResults1 = names.OrderBy(n => n).Where(n => n.StartsWith("S"));//方法语法 Lambda 表达式
                                                                                   // var queryResults = names.OrderByDescending(n => n).Where(n => n.StartsWith("S"));
            foreach (var item in queryResults)
                Console.WriteLine(item);
            Console.ReadKey();

2.1  from语句   

创建一个LINQ表达式必须要以from子句开头

单个from语句

          //获取数据
            string[] a = { "日本","德国","英国","美国","澳大利亚"};
            //创建查询,创建一个LINQ表达式必须要以from子句开头
            var myQuery = from n in a where n.IndexOf("国") > 0 select n;
            //执行查询
            foreach(var item in myQuery)
            {
                Console.WriteLine(item);
            }
            Console.ReadKey();

 

 

 复合from子句

如果一个集合中的某个对象依旧是一个集合,就可以使用from子句进行筛选。

    public class CustomerInfo1
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public List<string> TelTable { get; set; }
    }
    class Test03_MultiFrom
    {
        static void Main(string[] args)
        {
            //获取数据源
            List<CustomerInfo1> customer = new List<CustomerInfo1>
            {
                new CustomerInfo1{Name = "郭啸天",Age = 100,TelTable = new List<string>{"123321","321123"}},
                new CustomerInfo1{Name = "郭靖",Age = 80,TelTable = new List<string>{"456654","654456"}},
                new CustomerInfo1{Name = "郭芙", Age = 60,TelTable = new List<string>{"789987","987789"}}
            };
            //创建查询
            var query = from CustomerInfo1 ci in customer
                        from tel in ci.TelTable
                        where tel.IndexOf("789987") > -1
                        select ci;
 var query1=customer.SelectMany(c => c.TelTable, (c,r) => new { CustomerInfo1 = c, Tel = r }).Where(u=>u.Tel.IndexOf("789987")>-1); //执行查询 foreach (var item in query) { Console.WriteLine("姓名:{0} 年龄:{1}", item.Name, item.Age); foreach (var tel in item.TelTable) { Console.WriteLine("电话:{0}", tel); } } Console.ReadKey(); } }

2.2 where 语句

where子句的作用就是筛选元素,除了开始和结束位置, where子句几乎可以出现在LINQ表达式的任意位置。一个LINQ表达式中可以有where子句,也可以没有;可以有一个,可以有多个;多个where子句之间的关系相当于逻辑“与”,每个where子句可以包含1个或多个逻辑表达式,这些条件成为“谓词”,多个谓词之间用布尔运算符隔开,比如逻辑“与”用&&,逻辑“或”用||,而不是用SQL中的AND或OR。

//查询语句
var racrers = from r in Formulal.GetChampions() where r.Wins > 15 && (r.Country == "China" || r.Country == "UK") select r;
//扩展方法
var racres2 = Formulal.GetChampions() .Where(r => r.Wins > 15 && (r.Country == "China" || r.Country == "UK")) .Select(r => r);

这两种执行的结果都是一样的。但是并不是所有的LINQ查询都可以使用LINQ查询表达式完成,也不是所有的LINQ扩展方法都能够映射到LINQ查询表达式语句上。LINQ扩展方法使用的范围要比查询表达式更广泛,尤其是一些高级查询,只能或更多的是使用扩展方法完成。同时,这两种形式也可以组合使用。

//使用索引筛选,只能使用扩展方法,不能使用Linq查询语句
var racers3 = Formulal.GetChampions()
    .Where((r, index) => r.LastName.StartsWith("A") && index % 2 != 0);

2.3 排序子句 

 OrderBy/OrderByDescending/ThenBy/ThenByDescending

OrderBy():按升序对序列的元素进行排序。

ThenBy():按升序对序列中的元素进行后续排序。

OrderByDescending():按降序对序列的元素进行排序。

ThenByDescending():按降序对序列中的元素进行后续排序。

//查询语句
var racers3 = (from r in Formulal.GetChampions()
               orderby r.Country, r.LastName, r.FirstName ascending
               select r).Take(10);
//扩展方法
var racers4 = Formulal.GetChampions()
    .OrderBy(r => r.Country)
    .ThenBy(r => r.LastName)
    .ThenByDescending(r => r.FirstName)
    .Take(10);

2.4 分组

  GroupBy

如果要根据一个关键字值 对查询结果分组,可以使用group子句。对应的扩展方法为GroupBy()

//查询语句
var countries = from r in Formulal.GetChampions()
                group r by r.Country into g //将分组信息放入标识符g中
                orderby g.Count() descending, g.Key
                where g.Count() >= 2
                select new
                {
                    Country = g.Key,
                    Count = g.Count()
                }
//扩展方法
var countries2 = Formulal.GetChampions()
    .GroupBy(r => r.Country)
    .OrderByDescending(g => g.Count())
    .ThenBy(g => g.Key)
    .Where(g => g.Count() >= 2)
    .Select(g => new { Country = g.Key, Count = g.Count() });

2.5  Let子句  及   匿名类属性

上述的分组查询语句,中间多次调用了Count方法,使用let子句可以改变这种方式。let允许在LINQ查询中定义变量。

var countries = from r in Formulal.GetChampions()
                group r by r.Country into g
                let count = g.Count()
                orderby count descending, g.Key
                where count >= 2
                select new
                {
                    Country = g.Key,
                    Count = count
                };

使用方法语法时,为了避免Count方法被调用多次,可以使用Select方法创建一个匿名类型,将Count方法的结果作为匿名类的属性进行传递

var countries2 = Formulal.GetChampions()
    .GroupBy(r => r.Country)
    .Select(g => new { Group = g, Count = g.Count() })
    .OrderByDescending(g => g.Count)
    .ThenBy(g => g.Group.Key)
    .Where(g => g.Count >= 2)
    .Select(g => new
    {
        Country = g.Group.Key,
        Count = g.Count
    });

注意:应考虑根据let子句或Select方法创建的临时对象的数量 。查询大列表时,创建的大量对象需要以后进行垃圾收集 ,这可能对性能产生巨大影响。

2.6  join子句

如果一个数据源中元素的某个属性可以跟另一个数据源中元素的属性进行相等比较,那么这两个数据源可以用join子句进行关联。jion子句用equals关键字进行比较,而不是常见的==。
var racersAndTeams = (from r in racers
                       join t in teams on r.Year equals t.Year
                       orderby t.Year
                       select new
                          {
                                      r.Year,
                                      Champion = r.Name,
                                      Constructor = t.Name
                          }).Take(10);

左外连接

var racersAndTeams = (from r in racers
                      join t in teams on r.Year equals t.Year into rt
                      from t in rt.DefaultIfEmpty()
                      orderby r.Year
                      select new
                      {
                          r.Year,
                          Champion = r.Name,
                          Constructor = t == null ? "no constructor" : t.Name
                      }).Take(10);

 

2.7 集合操作

Intersect():通过使用的默认相等比较器对值进行比较,生成两个序列的交集。

Distinct():返回序列中通过使用指定的非重复元素。

Union():通过使用默认的相等比较器生成的两个序列的并集。

Except():通过使用默认的相等比较器对值进行比较,生成两个序列的差集。

           List<Order> orders = new List<Order>{
            new Order {ID="A",Amount=100},
            new Order {ID ="B",Amount =200},
            new Order {ID ="H",Amount =300}};


            var customersIDs = from c in customers
                               select c.ID;
            var ordersIDs = from o in orders
                            select o.ID;
            var customersWithOrders = customersIDs.Intersect(ordersIDs);//Intersect()
            foreach (var item in customersWithOrders )
                Console.WriteLine(item );
            Console.WriteLine("-------------------------");
            var ordersNoCustomers = ordersIDs.Except(customersIDs);//Except()
            foreach (var item in ordersNoCustomers )
                Console.WriteLine(item );
            Console.WriteLine("-------------------------");
            var allCustomersOrders = ordersIDs.Union(customersIDs);//Union()
            foreach (var item in allCustomersOrders)
                Console.WriteLine(item);
            //Console.ReadKey();

2.8 分区 

 Take和TakeWhile,Skip和SkipWhile

Take():从序列的开头返回指定的数量的连续元素。
TakeWhile():只要指定的条件为true,就返回序列中的元素,然后跳过其余元素。
Skip():跳过指定的数量的序列中的元素,然后返回剩余元素。
SkipWhile():只要指定的条件为真,就会跳过序列中的元素,然后返回剩余的元素。

int pageSize = 5;
int numberPages = (int)Math.Ceiling(Formulal.GetChampions().Count() / (double)pageSize);

for (int page = 0; page < numberPages; page++)
{
    Console.WriteLine("Page "+page);

    var racers = (from r in Formulal.GetChampions()
                  orderby r.LastName, r.FirstName
                  select r.FirstName + " " + r.LastName)
                .Skip(page * pageSize).Take(pageSize);

    foreach(var name in racers)
    {
        Console.WriteLine(name);
    }
    Console.WriteLine(  );
}

2.9 聚合操作符

聚合操作符(如Count、Sum、Min、Max、Average和Aggregate操作符)不返回一个序列,而返回一个值。
Count():返回序列中的元素数。
Sum():计算一系列数值的总和。
Min():返回值序列中的最小值。
Max():返回值序列中的最大值。
Average():计算一系列数值的平均值。
Aggregate(): 对一个序列应用累加器函数。

Console.WriteLine("Count():");
var query = from r in Formulal.GetChampions()
            let numberYears = r.Years.Count()
            where numberYears >= 3
            orderby numberYears descending, r.LastName
            select new
            {
                Name = r.FirstName + " " + r.LastName,
                TimesChampion = numberYears
            };

foreach(var r in query)
{
    Console.WriteLine(r.Name+" "+r.TimesChampion);
}

Console.WriteLine();
Console.WriteLine("Sum():");

var countries = (from c in from r in Formulal.GetChampions()
                           group r by r.Country into c
                           select new
                           {
                               Country = c.Key,
                               Wins = (from r1 in c select r1.Wins).Sum()
                           }
                 orderby c.Wins descending, c.Country
                 select c).Take(5);
foreach(var country in countries)
{
    Console.WriteLine(country.Country+" "+country.Wins);
}

 ==============================================相关知识点扩展==================================================

相关知识点扩展

1   var 、  dynamic  及匿名类型

 var model = new //3.0
                {
                    Id = 2,
                    Name = "undefined",
                    Age = 25,
                    ClassId = 2,
                 }  

Console.WriteLine(model.Id);     //编译错误
Console.WriteLine(model, Name);  //编译错误 

 
 dynamic model = new //4.0    dynamic避开编译器检查
                {
                    Id = 2,
                    Name = "undefined",
                    Age = 25,
                    ClassId = 2,
                 }  
Console.WriteLine(model.Id);     //编译不会报错
Console.WriteLine(model, Name);  //编译不会报错

2.   扩展方法

数据准备

    /// <summary>
    /// 学生实体
    /// </summary>
    public class Student
    {
        public int Id { get; set; }
        public int ClassId { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }

        public void Study()
        {
            Console.WriteLine("{0} {1}跟着Eleven老师学习.net高级开发", this.Id, this.Name);
        }

        public void StudyHard()
        {
            Console.WriteLine("{0} {1}跟着Eleven老师努力学习.net高级开发", this.Id, this.Name);
        }

        ////学习实战班
        //public void StudyPractise()
        //{
        //    Console.WriteLine("{0} {1}跟着Mark老师学习.net实战开发", this.Id, this.Name);
        //}
    }
    /// <summary>
    /// 扩展方法:静态类里面的静态方法,第一个参数类型前面加上this
    /// </summary>
    public static class ExtendMethod
    {
        public static void StudyPractise(this Student student)
        {
            Console.WriteLine("{0} {1}跟着Mark老师学习.net实战开发", student.Id, student.Name);
        }
   }
 

方法调用

//扩展方法调用,很像实例方法,就像扩展了Student的逻辑
//1 第三方的类,不适合修改源码,可以通过扩展方法增加逻辑
//优先调用实例方法,最怕扩展方法增加了,别人类又修改了
//2 适合组件式开发的扩展(.NetCore),定义接口或者类,是按照最小需求,但是在开发的时候又经常需要一些方法,就通过扩展方法 context.Response.WriteAsync 中间件的注册
//3 扩展一些常见操作
//会污染基础类型,一般少为object 没有约束的泛型去扩展


student.Study(); ExtendMethod.StudyPractise(student); student.StudyPractise();

3.  yield 迭代器

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace MyLinq
{
    /// <summary>
    /// http://www.cnblogs.com/YamatAmain/p/5016464.html
    /// 
    /// 含有yield的函数说明它是一个生成器,而不是普通的函数。当程序运行到yield这一行时,该函数会返回值,并保存当前域的所有变量状态;
    /// 等到该函数下一次被调用时,会从上一次中断的地方开始执行,一直遇到下一个yield, 程序返回值, 并在此保存当前状态; 如此反复,直到函数正常执行完成。
    /// 
    /// 迭代器模式是设计模式中行为模式(behavioral pattern)的一个例子,他是一种简化对象间通讯的模式,也是一种非常容易理解和使用的模式。
    /// 简单来说,迭代器模式使得你能够获取到序列中的所有元素 而不用关心是其类型是array,list,linked list或者是其他什么序列结构。
    /// 这一点使得能够非常高效的构建数据处理通道(data pipeline)--即数据能够进入处理通道,进行一系列的变换,或者过滤,然后得到结果。事实上,这正是LINQ的核心模式。
    /// 在.NET中,迭代器模式被IEnumerator和IEnumerable及其对应的泛型接口所封装。如果一个类实现了IEnumerable接 口,那么就能够被迭代;
    /// 调用GetEnumerator方法将返回IEnumerator接口的实现,它就是迭代器本身。迭代器类似数据库中的游标,他是 数据序列中的一个位置记录。
    /// 迭代器只能向前移动,同一数据序列中可以有多个迭代器同时对数据进行操作。
    /// </summary>
    public class YieldShow
    {
        /// <summary>
        /// 
        /// </summary>
        public void Show()
        {
            IEnumerable<int> iterable = this.CreateEnumerable();//1 不会直接执行
            //IEnumerator iterator = iterable.GetEnumerator();
            IEnumerator<int> iterator = iterable.GetEnumerator();
            Console.WriteLine("开始迭代");
            while (true)
            {
                Console.WriteLine("调用MoveNext方法……");
                Boolean result = iterator.MoveNext();//2 正式开启CreateEnumerable
                Console.WriteLine("MoveNext方法返回的{0}", result);
                if (!result)
                {
                    break;
                }
                Console.WriteLine("获取当前值……");
                Console.WriteLine("获取到的当前值为{0}", iterator.Current);
            }
            Console.ReadKey();
        }

        /// <summary>
        /// 普通获取数据
        /// </summary>
        /// <returns></returns>
        public IEnumerable<int> CommonMethod()
        {
            List<int> results = new List<int>();
            int counter = 0;
            int result = 1;

            while (counter++ < 10)
            {
                Thread.Sleep(1000);
                Console.WriteLine($"获取{counter}次数据");
                result = result * 2;
                results.Add(result);
            }
            return results;
        }
        /// <summary>
        /// yield获取数据
        /// </summary>
        /// <returns></returns>
        public IEnumerable<int> YieldMethod()
        {
            int counter = 0;
            int result = 1;
            while (counter++ < 10)
            {
                Thread.Sleep(1000);
                Console.WriteLine($"获取{counter}次数据");
                result = result * 2;
                yield return result;
            }
        }

        public IEnumerable<int> CreateEnumerable()
        {
            try
            {
                Console.WriteLine("{0} CreateEnumerable()方法开始", DateTime.Now);
                for (int i = 0; i < 5; i++)
                {
                    Console.WriteLine("{0}开始 yield {1}", DateTime.Now, i);
                    yield return i;
                    Console.WriteLine("{0}yield 结束", DateTime.Now);
                    if (i == 4)
                    {
                        yield break;//直接终结迭代  4会出现的,,
                    }
                }
                Console.WriteLine("{0} Yielding最后一个值", DateTime.Now);
                yield return -1;
                Console.WriteLine("{0} CreateEnumerable()方法结束", DateTime.Now);
            }
            finally
            {
                Console.WriteLine("停止迭代!");
            }
        }
    }
}

 

转自https://www.cnblogs.com/for-easy-fast/articles/12340925.html

标签:Count,Console,C#,Linq,WriteLine,var,new,select
From: https://www.cnblogs.com/castlewu/p/16987081.html

相关文章

  • 解决使用innobackupex备份mysql产生returned OS error 124【转】
    ###简介今天在使用innobackupex全量备份数据库的时候发生了下面的错误错误详情19070515:22:18>>logscannedupto(258819807308)xtrabackup:Generatingalist......
  • 【转载】安装Axure RP Extension for Chrome插件的简单方法
    在使用Chrome浏览器查看Axure的原型HTML文件时,会提示下载AxureRPExtensionforChrome插件!而插件在Google的服务器上根本下载不了。下面的网文可以让你只需三步,不用下载A......
  • C++小型公司人员信息管理系统(多态)
    C++小型公司人员信息管理系统(多态)1.实验题目及要求已有应用为:某公司包含多种员工类型:技术员,产品经理,销售员、销售经理。技术员(包含工号(6位:000001999999)、姓名、电话......
  • conda基本操作
    conda换到别的通道下载condainstallxxx–c通道地址清华镜像:https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main持久添加通道:condaconfigaddchannels......
  • 0基础→自动化测试框架实现:java + testng + httpclient + allure
    必备基础java基础配置文件解析(properties)fastjson的使用(处理json字符串、json数组)jsonpath的使用java操作excel(通过POIHttpClient的使用(get、post请求)TestNG用法 自动化测......
  • 痞子衡嵌入式:浅谈i.MXRT10xx系列MCU外接24MHz晶振的作用
    大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是i.MXRT10xx系列MCU外接24MHz晶振的作用。痞子衡之前写过一篇关于时钟引脚的文章​​《i.MXRT1xxx......
  • YACS 11 月甲题解
    https://iai.sh.cn/contest这把还是简单的,难度对标普及组。所有题解均口胡。T1观察&性质你扫左端点,然后维护以当前左端点最长的合法子段,显然右端点单不降,因为当你......
  • Python绘制柱状图之可视化神器Pyecharts
    ✅作者简介:热爱科研的算法开发者,Python、Matlab项目可交流、沟通、学习。......
  • unicloud 模糊查询
    constdb=uniCloud.database();constwork=db.collection('workIndex')constfood=db.collection('centerFoodList')//food.limit().get()//.doc.remove//......
  • Android 使用ViewTreeLifecycleOwner获取Lifecycle
    本文出自​​【赵彦军的博客】​​文章目录​​ViewTreeLifecycleOwner是什么?​​​​实现原理?​​​​ComponentActivity​​​​Fragment​​​​DialogFragment​​​​......