• c# Linq查询


    c#提供的ling查询极大的遍历了集合的查询过程,且使用简单方便,非常的有用。

    下面将分别用简单的例子说明:ling基本查询、延迟查询属性、类型筛选、复合from字句、多级排序、分组查询、联合查询、合并、分页、聚合操作符、并行linq、取消长时间运行的并行ling查询。

    Lambda表达式简介:

    复制代码
     /*Lambda表达式:Lambda 表达式是一种可用于创建委托或表达式目录树类型的匿名函数
                 表达式位于 => 运算符右侧的 lambda 表达式称为“表达式 lambda”。
                 * (input parameters) => expression 
                 * 示例:*/
                  delegate int del(int i);  
                  static void Main(string[] args)
                  { 
                       del myDelegate = x => x * x;  
                       int j = myDelegate(5); //最后j = 25  
                   } 
                
    复制代码
    • 基本查询

    语句:

     var query = from r in listStudents where r.score < 60 orderby r.score descending select r;
     //var q2 = listStudents.Where(r => r.score < 60).OrderByDescending(r => r.score).Select(r => r) ;//或使用Lambda表达式

    例子:

    复制代码
     /// <summary>
            /// 学生结构体
            /// </summary>
            struct Student
            {
                /// <summary>
                /// 姓名
                /// </summary>
                public string name;
                /// <summary>
                /// 年龄
                /// </summary>
                public int age;
                /// <summary>
                /// 班号
                /// </summary>
                public int grade;
                /// <summary>
                /// 分数
                /// </summary>
                public float score;
            }
    /// <summary>
            /// linq
            /// 基本查询
            /// </summary>
            static void Linq1()
            {
                #region 构造查询数据
                List<Student> listStudents = new List<Student>();
                Random pRandom = new Random();
                for (int i = 1; i < 50; i++)
                {
                    float sc = pRandom.Next(0, 100);
                    int age = pRandom.Next(8, 13);
                    int gde = pRandom.Next(1, 6);
    
                    string name = "";
                    switch (pRandom.Next(0, 6))
                    {
                        case 1: name = "周xxx"; break;
                        case 2: name = "李xxx"; break;
                        case 3: name = "孙xxx"; break;
                        case 4: name = "钱xxx"; break;
                        default: name = "赵xxx"; break;
                    }
    
                    Student psdt = new Student();
                    psdt.name = name;
                    psdt.age = age;
                    psdt.grade = gde;
                    psdt.score = sc;
                    listStudents.Add(psdt);
                }
                #endregion
                //从50个学生中选择出不及格的人员名单并按分数降序排列
                var query = from r in listStudents where r.score < 60 orderby r.score descending select r;
                //var q2 = listStudents.Where(r => r.score < 60).OrderByDescending(r => r.score).Select(r => r) ;//或使用Lambda表达式
                //orderby升序即从小到大,orderby r.score descending降序即从大到小
    
                Console.WriteLine("不及格的人员名单:");
                foreach (Student st in query)
                {
                    Console.WriteLine("***************");
                    Console.WriteLine("姓名:"+st.name);
                    Console.WriteLine("班级:"+st.grade);
                    Console.WriteLine("年龄:"+st.age);
                    Console.WriteLine("分数:"+st.score);
                }
                Console.ReadKey();
            }
    复制代码
    • 延迟查询属性

    linq查询为延迟查询,只需构造一次查询语句,可以多次使用。

    例子:

    复制代码
    /// <summary>
            /// Linq
            /// 延迟查询
            /// linq查询为延迟查询,只需构造一次查询语句,可以多次使用
            /// </summary>
            static void Linq2()
            {
                #region 构造查询数据
                List<string> lists = new List<string> { "Jack","Pet","Hant","Li","Kkk"};
                
                #endregion
                var query = from r in lists where r.StartsWith("J") select r;
                Console.WriteLine("第一次查询结果:");
                foreach (string st in query)
                {
                    Console.WriteLine( st);
                }
    
                Console.WriteLine("第二次查询结果:");
                lists.Add("Jone");
                lists.Add("Jimi");
                lists.Add("Johu");
                foreach (string st in query)
                {
                    Console.WriteLine(st);
                }
    
                Console.ReadKey();
                /*
                 输出结果:
                 * 第一次:Jack
                 * 第二次:Jack Jone Jimi Johu
                 */
            }
    复制代码
    • 类型筛选

    利用OfType方法可以把特定类型数据筛选出来。

    例子:

    复制代码
     /// <summary>
            /// Linq类型筛选-ofType
            /// </summary>
            static void Linq3()
            {
                object[] pList = new object[] { 1,"one",2,"two",3,"three"};
                var query = pList.OfType<string>();
                foreach (var st in query)
                {
                    Console.WriteLine(st);
                }
                Console.ReadKey();
                /*
                输出结果:
                * one two three
                */
            }
    复制代码
    • 复合from子句

    语句:

     var query = from s in listStudents 
                            from n in s.name 
                            where n == '赵' orderby s.score descending 
                            select s.grade + "班-" + s.name + ",分数" + +s.score;
                /*查询出所有姓赵的学生的班级、姓名、分数信息,并按分数由高到低排序*/

    例子:

    View Code
    • 多级排序

    语句:

     //参数越靠前,优先级越高
                //先按score排序,当分数相同时再按grade排序...依次类推
                var query = from s in listStudents orderby s.score, s.grade, s.age, s.name select s;

    例子:

    复制代码
     /// <summary>
            /// 多级排序
            /// </summary>
            static void Linq5()
            {
                #region 构造查询数据
                List<Student> listStudents = new List<Student>();
                Random pRandom = new Random();
                for (int i = 1; i < 50; i++)
                {
                    float sc = pRandom.Next(0, 100);
                    int age = pRandom.Next(8, 13);
                    int gde = pRandom.Next(1, 6);
    
                    string name = "";
                    switch (pRandom.Next(0, 6))
                    {
                        case 1: name = "周xxx"; break;
                        case 2: name = "李xxx"; break;
                        case 3: name = "孙xxx"; break;
                        case 4: name = "钱xxx"; break;
                        default: name = "赵xxx"; break;
                    }
    
                    Student psdt = new Student();
                    psdt.name = name;
                    psdt.age = age;
                    psdt.grade = gde;
                    psdt.score = sc;
                    listStudents.Add(psdt);
                }
                #endregion
                //参数越靠前,优先级越高
                //先按score排序,当分数相同时再按grade排序...依次类推
                var query = from s in listStudents orderby s.score, s.grade, s.age, s.name select s;
                foreach (Student st in query)
                {
                    Console.WriteLine("***************");
                    Console.WriteLine("姓名:" + st.name);
                    Console.WriteLine("班级:" + st.grade);
                    Console.WriteLine("年龄:" + st.age);
                    Console.WriteLine("分数:" + st.score);
                }
                Console.ReadKey();
            }
    复制代码
    • 分组

    语句:

    复制代码
     //按国家分组,并选出大于2的组,形成新的集合
                var query = from r in listChampion
                            group r by r.country into g
                            orderby g.Count() descending, g.Key
                            where g.Count() >= 2
                            select
                                new { country = g.Key, count = g.Count() };
    复制代码

    例子:

    复制代码
     /// <summary>
            /// 分组
            /// </summary>
            static void Linq6()
            {
                List<Champions> listChampion = new List<Champions>();
                listChampion.Add(new Champions() { name = "张**", country = "中国" });
                listChampion.Add(new Champions() { name = "赵**", country = "中国" });
                listChampion.Add(new Champions() { name = "李**", country = "中国" });
                 listChampion.Add(new Champions() { name = "李**", country = "中国" });
                listChampion.Add(new Champions() { name = "Peter", country = "美国" });
                listChampion.Add(new Champions() { name = "Hune", country = "美国" });
                  listChampion.Add(new Champions() { name = "Hune", country = "美国" });
                listChampion.Add(new Champions() { name = "Jack", country = "俄罗斯" });
                  listChampion.Add(new Champions() { name = "Jack", country = "俄罗斯" });
                listChampion.Add(new Champions() { name = "Jimi", country = "英国" });
                //按国家分组,并选出大于2的组,形成新的集合
                var query = from r in listChampion
                            group r by r.country into g
                            orderby g.Count() descending, g.Key
                            where g.Count() >= 2
                            select
                                new { country = g.Key, count = g.Count() };
                foreach (var o in query)
                {
                    Console.WriteLine("国家:{0},冠军数:{1}个", o.country, o.count);
                }
                Console.ReadKey();
            }
    复制代码
    • 联合查询-join

    语句:

    复制代码
     //查询出集合qSt中year等于集合qSc中year的元素并形成新的集合
                var qjoin = from r in qSt 
                            join c in qSc 
                            on r.year equals c.year 
                            select new 
                            {
                                Year = r.year, 
                                stName = r.name,
                                scName = c.name 
                            };
    复制代码

    例子:

    复制代码
      /// <summary>
            /// 联合查询-join
            /// </summary>
            static void Linq7()
            {
                List<s> pSt = new List<s>();
                pSt.Add(new s() {year=1999,name="xxx" });
                pSt.Add(new s() { year = 2000, name = "xxx" });
                pSt.Add(new s() { year = 2001, name = "xxx" });
                pSt.Add(new s() { year = 2010, name = "xxx" });
                List<school> pSc = new List<school>();
                pSc.Add(new school() { year = 1999, name = "***" });
                 pSc.Add(new school() { year = 2001, name = "***" });
                pSc.Add(new school() { year = 2002, name = "***" });
                pSc.Add(new school() { year = 2010, name = "***" });
                pSc.Add(new school() { year = 2012, name = "***" });
    
                var qSt = from r in pSt where r.year >= 2000 select r;
                var qSc = from r in pSc where r.year >= 2000 select r;
    
                //查询出集合qSt中year等于集合qSc中year的元素并形成新的集合
                var qjoin = from r in qSt 
                            join c in qSc 
                            on r.year equals c.year 
                            select new 
                            {
                                Year = r.year, 
                                stName = r.name,
                                scName = c.name 
                            };
    
                foreach (var ite in qjoin)
                {
                    Console.WriteLine(ite.Year + " " + ite.scName + " " + ite.stName);
                    Console.WriteLine("");
                }
                Console.ReadKey();
            }
    复制代码
    • 合并-zip()

    .Net4.0新增,可对两个相关的序列进行合并。

    语句:

      /*若合并两项项数不同,则在达到较小集合的末尾时停止*/
                var qZip = qSc.Zip(qSt, (first, second) =>string.Format("Year:{0},Name:{1}.", first.Year,second.Name));//返回值qZip为字符串集合

    例子:

    复制代码
     /// <summary>
            /// 合并-zip()-.Net4.0新增,可对两个相关的序列进行合并
            /// </summary>
            static void Linq8()
            {
                List<s> pSt = new List<s>();
                pSt.Add(new s() { year = 1999, name = "一xxx" });
                pSt.Add(new s() { year = 2000, name = "二xxx" });
                pSt.Add(new s() { year = 2001, name = "三xxx" });
                pSt.Add(new s() { year = 2010, name = "四xxx" });
                pSt.Add(new s() { year = 2010, name = "五xxx" });
                List<school> pSc = new List<school>();
                pSc.Add(new school() { year = 1999, name = "1***" });
                pSc.Add(new school() { year = 2012, name = "2***" });
                pSc.Add(new school() { year = 2012, name = "3***" });
                pSc.Add(new school() { year = 2012, name = "4***" });
                pSc.Add(new school() { year = 2012, name = "5***" });
    
                var qSt = from r in pSt where r.year >= 2000 orderby r.year select new { Year = r.year, Name = r.name };
                var qSc = from r in pSc where r.year >= 2000 orderby r.year select new { Year = r.year, Name = r.name };
                /*若合并两项项数不同,则在达到较小集合的末尾时停止*/
                var qZip = qSc.Zip(qSt, (first, second) =>string.Format("Year:{0},Name:{1}.", first.Year,second.Name));//返回值qZip为字符串集合
               
                foreach (var ite in qZip)
                {
                    Console.WriteLine(ite);
                }
                Console.ReadKey();
    
            }
    复制代码
    • 分区(分页)

    通过Take()和Skip()实现只显示部分查询结果。

    语句:

     //通过skip跳过指定数量的元素,再通过take提取固定长度元素,可实现分页
                    var qr = (from r in listStudents orderby r.score descending select r).Skip(i * pageSize).Take(5);
                    //var qr2 = listStudents.OrderByDescending(r => r.score).Select(r => r).Skip(i * pageSize).Take(5);//或

    例子

    复制代码
     /// <summary>
            /// 分区(分页)-通过Take()和Skip()实现只显示部分查询结果
            /// </summary>
            static void Linq9()
            {
                #region 构造查询数据
                List<Student> listStudents = new List<Student>();
                Random pRandom = new Random();
                for (int i = 1; i < 50; i++)
                {
                    float sc = pRandom.Next(0, 100);
                    int age = pRandom.Next(8, 13);
                    int gde = pRandom.Next(1, 6);
    
                    string name = "";
                    switch (pRandom.Next(0, 6))
                    {
                        case 1: name = "周xxx"; break;
                        case 2: name = "李xxx"; break;
                        case 3: name = "孙xxx"; break;
                        case 4: name = "钱xxx"; break;
                        default: name = "赵xxx"; break;
                    }
    
                    Student psdt = new Student();
                    psdt.name = name;
                    psdt.age = age;
                    psdt.grade = gde;
                    psdt.score = sc;
                    listStudents.Add(psdt);
                }
                #endregion
    
                int pageSize = 5;
                int numofPage = (int)Math.Ceiling(listStudents.Count /(double)pageSize);
    
                for (int i = 0; i < numofPage; i++)
                {
                    Console.WriteLine("第{0}页", i);
    
                    //通过skip跳过指定数量的元素,再通过take提取固定长度元素,可实现分页
                    var qr = (from r in listStudents orderby r.score descending select r).Skip(i * pageSize).Take(5);
                    //var qr2 = listStudents.OrderByDescending(r => r.score).Select(r => r).Skip(i * pageSize).Take(5);//或
                    foreach (var ite in qr)
                    {
                        Console.WriteLine(ite.name);
                        Console.WriteLine(ite.score);
                    }
                    Console.WriteLine("");
                }
                Console.ReadKey();
            }
    复制代码
    • 并行linq

    并行查询可以分解查询的工作,使其分布在多个线程上。当pc拥有多个cpu时,可以看到并行查询带来的改进效果。并行LINQ适用于大型的集合查询,并拥有一定的优势。使用

    System.Collections.Concurrent.Partitioner.Create
    可以手动创建分区器。

    语法:

    var sum2 = (from x2 in data.AsParallel() where x2 > 20 select x2).Sum();//并行查询
    
    //var sum3 = data.AsParallel().Where(x3 => x3 > 20).Sum();//或并行查询(Lambda表达式)

    例子:

    复制代码
     /// <summary>
            /// 并行linq
            /// </summary>
            static void Linq11()
            {
                Console.WriteLine("开始构造大数组...");
                //构造大数组
                const int count = 100000000;
                var data = new int[count];
                var r = new Random();
                for (int i = 0; i < count; i++)
                {
                    data[i] = r.Next(40);
                }
                Console.WriteLine("开始计算...");
                var st = System.DateTime.Now;
                var sum = (from x in data where x > 20 select x).Sum();//常规linq-耗时1.8641s
                var st2 = System.DateTime.Now;
                var sum2 = (from x2 in data.AsParallel() where x2 > 20 select x2).Sum();//并行查询-耗时0.6620s
    
                //var sum3 = data.AsParallel().Where(x3 => x3 > 20).Sum();//或并行查询----x3 => x3 > 20(Lambda表达式)
                var st3 = System.DateTime.Now;
    
                /*Partitioner.Create
                 手动创建分区器
                 * Create具有多个重载,可依据需求进行分区
                 */
                var sum4 = (from c in System.Collections.Concurrent.Partitioner.Create(data, true).AsParallel() where c > 20 select c).Sum();
    
                var dt1 = st2 - st;
                var dt2 = st3 - st2;
                Console.WriteLine("常规linq耗时:{0}s",dt1.TotalSeconds.ToString());
                Console.WriteLine("并行linq耗时:{0}s", dt2.TotalSeconds.ToString());
                Console.ReadKey();
            }
    复制代码

     输出结果:

    可以粗鲁的认为并行linq对于大集合的查询是优势比较明显的。

    • 取消长时间运行的并行linq查询

    对于并行ling而言,可以设置可以利用System.Threading.CancellationTokenSource设置取消操作。

    语法:

     //通过.WithCancellation(cts.Token)设置
                        var sum = (from x in data.AsParallel().WithCancellation(cts.Token) where x < 20 select x).Average();

    例子:

    复制代码
     /// <summary>
            /// 取消长时间运行的并行linq查询
            /// </summary>
            static void Linq12()
            {
                //构造大数组
                const int count = 100000000;
                var data = new int[count];
                var r = new Random();
                for (int i = 0; i < count; i++)
                {
                    data[i] = r.Next(40);
                }
    
                var cts = new System.Threading.CancellationTokenSource();
    
                new System.Threading.Thread(() =>
                {
                    try
                    {
                        //通过.WithCancellation(cts.Token)设置
                        var sum = (from x in data.AsParallel().WithCancellation(cts.Token) where x < 20 select x).Average();
                        Console.WriteLine("sum:{0}", sum);
                    }
                    catch(OperationCanceledException ex)
                    {
                        Console.WriteLine(ex.Message);
                    }
                }).Start();
    
                Console.WriteLine("计算开始...");
                Console.WriteLine("取消请按n!");
                var rk = Console.Read();
                if(rk=='n'||rk=='N')
                {
                    cts.Cancel();
                }
    
            }
    复制代码

    至此,对于LINQ已经有了一个基本的了解。

  • 相关阅读:
    C# 文件流读写方法汇总
    C#中try catch finally的执行顺序(转载)
    Qt利用QPainter自绘实现热感应图效果
    Qt利用QPainter自绘实现扫描雷达功能scanneritem
    Qt5利用自绘QPainter实现旋转按钮MySpinButton
    Qt实现范围滑动条SuperSlider
    Qtt利用QPainter实现铵扭switchButton
    Qt5利用自绘QPainter实现水波纹进度条QProgressBarWater
    Qt5利用自绘实现云台GaugeCloud
    Qt5利用自绘实现遥感
  • 原文地址:https://www.cnblogs.com/nimorl/p/12626718.html
Copyright © 2020-2023  润新知