• 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏吧

别再眼高手低了! 这些Linq方法都清楚地掌握了吗?

开发技术 开发技术 3周前 (09-12) 24次浏览

不要再眼高手低了,这些Enumerable之常见Linq扩展方法都清楚掌握了吗?其实这是对我自己来说的!

例如:一个人这个技术掌握了一点那个技术也懂一点,其他的好像也了解一些,感觉自己啥都会一点,又觉得自己啥都不会!

好像是处于那种技术疯癫的症态中!独孤求败!其实主要还是不愿意动手实践一下,总是会对低的技术看不上,高的技术又学不懂,或者是半懂不懂,或者是坚持不下去等等,

这些都是不可取的,加油吧骚年!

步入正轨:

1:什么是Linq(下面专业的名词解释参考来自于网络以及官网的文档,点击这里)

   1.1:LINQLanguage Integrated Query的简称,它是集成在.NET编程语言(例如:C#、VB.NET等)中的一种特性,目的是为.NET Framework提供更加通用和便利的信息查询方式,

    并且它对数据源提供了广泛的支持,而不仅仅局限于关系型数据库和XML。

  1.2:LINQ定义了一组标准查询操作符用于在所有基于.NET平台的编程语言中更加直接地声明跨越、过滤和投射操作的统一方式,标准查询操作符允许查询作用于所有基于IEnumerable接口的源,

    比如Array,List,XML,DOM或者是SQL Server数据表。并且它还允许适合于目标域或技术的第三方特定域操作符来扩大标准查询操作符集,更重要的是,第三方操作符可以用它们自己的提供附加服务的实现来自由地替换标准查询操作符,

    根据LINQ模式的习俗,这些查询喜欢采用与标准查询操作符相同的语言集成和工具支持

 2:使用Linq有啥好处

   2.1:使用LINQ的目的是为了提供一个解决对象关系映射问题的方案,同时简化对象和数据源的交互。LINQ最终发展成为一个通用语言集成查询的工具包。

  2.2:LINQ正如它的名字“集成查询语言”的含义一样,它提供给程序员一个统一的编程界面。程序员不需要关心他将要操作的将是关系数据库还是XML,

    甚至是远程的对象,它都采用同样的查询方式。就如同通过T-SQL操纵数据库一样,不管是OracleSyBase还是SQL Server,他们的Select语法都是一样的。

  2.3:有了LINQ程序员便可以不再沉泥于不同的数据访问技术的学习。不管编程语言如何发展,还是数据库技术的发展,都不再需要程序员进行学习,

    数据存储的效率由数据库厂商进行优化,灵活的数据操作方法由数据访问中间件厂商提供,程序员只需要编写业务逻辑,

  2.4:提升开发效率等

3:C# Linq类库

  在C#中,LINQ相关类库都在System.Linq命名空间下。该命名空间提供支持使用LINQ进行查询的类和接口,其中最重要的是两个类和两个接口。

  IEnumerable接口:它表示可以查询的数据集合,一个查询通常是逐个对集合中的元素进行筛选操作,返回一个新的IEnumerable对象,用来保存查询结果。

  IQuerable接口:它继承IEumerable接口,表示一个可以查询的表达式目录树。

  Enumerable类,它通过对IEnumerable提供扩展方法,实现LINQ标准查询运算符。包括过滤、导航、排序、查询、联接、求和、求最大值、求最小值等操作。

  Queryable类:它通过对IQueryable提供扩展方法,实现LINQ标准查询运算符。包括过滤、导航、排序、查询、联接、求和、求最大值、求最小值等操作

这里我想说的是:记住只一点就不会搞混淆:IQueryable通常是查询操作数据库中的数据,IEnumerable通常是处理内存中的数据

4:Linq 的种类

  根据数据源类型,可以将LINQ技术分成如下所述的3个主要技术方向。
  1:LINQ to Objects 数据源为实现了接口IEnumerable或IQeryable的内存数据集合,这也是LINQ的基础。
  2:LINQ to XML 数据源为XML文档,这里通过XElement、XAttribute等类将XML文档数据加载到内存中,通过LINQ进行数据查询。
  3:LINQ to ADO.Net 

想进一步了解上面的几种类型的使用,大家可以参考网络上的资源(比较多,这里就不再展示了)谢谢!

5:Core3.1下面的Linq有哪些常见的扩展方法,怎么使用?如下简单的demo案例:

别再眼高手低了! 这些Linq方法都清楚地掌握了吗?别再眼高手低了! 这些Linq方法都清楚地掌握了吗?

  Aggregate 的使用

  {
                List<int> listnum = new List<int>();
                for (int i = 1; i <= 100; i++)
                {
                    listnum.Add(i);
                }
                //Aggregate 总数;合计
                var getAggregateData = listnum.Aggregate((a, b) =>
                  {
                      return a + b;
                  });
                Console.WriteLine("从1+2+3+**100={0}", getAggregateData);

                //Aggregate 求偶数的个数 0:表示从0开始; totalCount:记录总的次数; gonumber:要依次遍历的元素
                int gettotalcount = listnum.Aggregate(0, (totalCount, gonumber) =>
                   {
                       return gonumber % 2 == 0 ? totalCount += 1 : totalCount;
                   });
                Console.WriteLine("偶数的个数有:{0}个", gettotalcount);
  }

别再眼高手低了! 这些Linq方法都清楚地掌握了吗?

别再眼高手低了! 这些Linq方法都清楚地掌握了吗? 别再眼高手低了! 这些Linq方法都清楚地掌握了吗?

All 的使用 需要所有的条件都满足才行,只要有一个条件不满足就不会再执行下去

明明有两只猪都满足条件,单数只查询到老猪的数据 是不是和起初想的不一样呢?其实想想才恍然大悟 all的含义就是全部的意思,

这里只要不满足条件就没有必要再往下面去查找了,起到提升效率的作用

{
                List<Pig> pigs = new List<Pig> {
                    new Pig{ pid="Z003",name="老猪",age=10},
                    new Pig{ pid="Z001",name="小猪",age=1},
                    new Pig{ pid="Z002",name="青年猪",age=3},
                    new Pig{ pid="Z004",name="八戒",age=500},
                };
                var newlist = new List<Pig>();
                var pigallConditionok = pigs.All(p =>
                {
                    if (p.age >= 10)
                    {
                        newlist.Add(p); return true;
                    }
                    else { return false; }
                });
                Console.WriteLine(pigallConditionok ? "所有的猪都满足大于10岁" : "不是所有的猪都满足大于10岁");
                Console.WriteLine($"所有的猪都满足大于10岁的名称有:{string.Join(", ", newlist.Select(c => c.name))},其年龄分别为:{string.Join(", ", newlist.Select(c => c.age))}");            

 别再眼高手低了! 这些Linq方法都清楚地掌握了吗?

 Any 的使用 ,来确定集合是否包含任何元素

List<Pig> pigs = new List<Pig> {
                new Pig{ pid="Z003",name="老猪",age=10},
                new Pig{ pid="Z001",name="小猪",age=1},
                new Pig{ pid="Z002",name="青年猪",age=3},
                new Pig{ pid="Z004",name="八戒",age=500},
            };
            var newlist = new List<Pig>();
            if (pigs != null && pigs.Any())
            {
                newlist = pigs.Where(c => c.age >= 10).ToList();
                Console.WriteLine($"所有的猪都满足大于10岁的名称有:{string.Join(", ", newlist.Select(c => c.name))},其年龄分别为:{string.Join(", ", newlist.Select(c => c.age))}");
            }
            else
            {
                Console.WriteLine("没有数据!");
            }

别再眼高手低了! 这些Linq方法都清楚地掌握了吗?

 Append的使用 将值追加到序列的末尾。 此方法不修改集合中的元素。 相反,它使用新元素创建集合的副本

List<string> liststr = new List<string> { "你好", ":" };
            liststr.Append("帅哥");
            Console.WriteLine(string.Join(" ", liststr));
            Console.WriteLine("啥,为啥没有效果???");
            Console.WriteLine(string.Join(" ", liststr.Append(Console.ReadLine())));
            Console.WriteLine("你可以说一些肉麻的话:");
            Console.WriteLine(string.Join(" ", liststr.Append(Console.ReadLine())));

 别再眼高手低了! 这些Linq方法都清楚地掌握了吗?

 AsEnumerable的使用 返回类型化为 IEnumerable<T> 的输入

 MyDog<string> mydog = new MyDog<string> { "absdsdsd", "grgrfefs", "wqethh", "mhngf" };

            //直接使用指定的委托非法MyWhere() 我们想查询集合中包含 s的元素有哪些
            var newlistMywhere = mydog.MyWhere(c => c.Contains('s')).ToList();

            //AsEnumerable() 后 会隐藏MyDog自定义的MyWhere方法,而是使用Linq系统自带的where方法
            var newlistLinqWhere = mydog.AsEnumerable().Where(c => c.Contains("s"));

            Console.WriteLine(string.Join(" ; ", newlistMywhere));
            Console.WriteLine(string.Join(" | ", newlistMywhere));

 别再眼高手低了! 这些Linq方法都清楚地掌握了吗?

 Average的使用  计算数值序列的平均值。比较简单的使用

IEnumerable<decimal> list = new List<decimal> { 88, 70, 90, 60, 85, 100 };
            decimal avgScore = list.Average();
            Console.WriteLine("平均分是(保留小数点后两位数):" + Math.Round(avgScore, 2));

 别再眼高手低了! 这些Linq方法都清楚地掌握了吗?

Cast的使用 将 IEnumerable 的元素强制转换为指定的类型

ArrayList arlist = new ArrayList { "99", "88", "100" };
            var newlist = arlist.Cast<string>().OrderByDescending(c => c).Select(c => c.ToString()).ToList();
            Console.WriteLine("强转前: " + string.Join(" ", arlist));
            Console.WriteLine("强转之后: " + string.Join(" ", newlist));

 别再眼高手低了! 这些Linq方法都清楚地掌握了吗?

Concat的使用连接两个序列

 List<Pig> list01 = new List<Pig> { new Pig { name = "八戒" }, new Pig { name = "喜欢" } };
            List<Pig> list02 = new List<Pig> { new Pig { name = "嫦娥仙女" }, new Pig { name = "也去过高老庄" } };

            var listname = list01.Select(c => c.name).Concat(list02.Select(a => a.name));
            Console.WriteLine(string.Join(", ", listname));

 别再眼高手低了! 这些Linq方法都清楚地掌握了吗?

Contains的使用 确定序列是否包含指定的元素。

  List<string> list = new List<string> { "小猪", "青年猪", "老猪", "八戒" };
            if (list.Contains("八戒"))
            {
                Console.WriteLine("八戒藏在高老庄");
            }
            else { Console.WriteLine("不知八戒的去向"); }

 别再眼高手低了! 这些Linq方法都清楚地掌握了吗?

Count的使用 返回序列中的元素数量

 List<string> list = new List<string> { "小猪", "青年猪", "老猪", "八戒" };
            Console.WriteLine(list.Count);

 别再眼高手低了! 这些Linq方法都清楚地掌握了吗?

DefaultIfEmpty 返回 IEnumerable<T> 的元素;如果序列为空,则返回一个具有默认值的单例类集合。

 List<Pig> list = new List<Pig> {
                      new Pig{pid="p001",name="小猪",age=1 },
                      new Pig{pid="p002",name="青年猪",age=2 },
                      new Pig{pid="p003",name="老猪",age=10 },
                      new Pig{pid="p004",name="八戒",age=500 },

            };
            var newlist = list.Where(c => c.age > 500).ToList().DefaultIfEmpty().ToList();
            var newlist2 = list.Where(c => c.age > 500).ToList().DefaultIfEmpty<Pig>(list.Last()).ToList();

            Console.WriteLine(string.Join(", ", newlist.Select(c => c == null ? "没有找到实体数据" : c.name)));
            Console.WriteLine(string.Join(", ", newlist2.Select(c => c.name)));

 别再眼高手低了! 这些Linq方法都清楚地掌握了吗?

Distinct的使用 返回序列中的非重复元素。 比较简单和好理解吧,宝宝们!

 List<string> list = new List<string> { "小猪", "青年猪", "老猪", "八戒", "青年猪", "老猪", };
            Console.WriteLine("获取到不重复的元素有:" + string.Join(",", list.Distinct()));

 别再眼高手低了! 这些Linq方法都清楚地掌握了吗?

ElementAt的使用 返回序列中指定索引处的元素

 public static TSource ElementAt<TSource>(this System.Collections.Generic.IEnumerable<TSource> source, int index);
            List<string> list = new List<string> { "小猪", "青年猪", "老猪", "八戒", "青年猪", "老猪", };

            Console.WriteLine("ElementAt是从零开始的,集合第4个元素是{0}", list.ElementAt(3));

 别再眼高手低了! 这些Linq方法都清楚地掌握了吗?

ElementAtOrDefault的使用 返回序列中指定索引处的元素;如果索引超出范围,没有发现会抛异常。

 List<string> list = new List<string> { "白菜", "萝卜", "西红柿", "茄子" };
            string getstr = list.ElementAtOrDefault(5);
            if (!string.IsNullOrEmpty(getstr))
                Console.WriteLine("我比较喜欢吃的蔬菜是:" + getstr);
            else
                Console.WriteLine("超出选择的范围,系统为您选择了一个蔬菜,是:" + list.ElementAtOrDefault(3));

 别再眼高手低了! 这些Linq方法都清楚地掌握了吗?

 Empty的使用  返回具有指定类型参数的空 IEnumerable<T>,通常我们后端些Core WebApi 接口的时候。

//前端会要求没有数据帮忙返回空的数组,不要返回null,这时 Empty就可以很好的上任,也不容易跑出空指针类似的错误

 List<Pig> list = new List<Pig> {
                    new Pig{pid="p001",name="小猪",age=1 },
                    new Pig{pid="p002",name="青年猪",age=2 },
                    new Pig{pid="p003",name="老猪",age=10 },
                    new Pig{pid="p004",name="八戒",age=500 }
            };
            //Enumerable.Empty<Pig>().ToList(); 会返回一个空的集合
            var newList = list.Where(c => c.age > 500).ToList() ?? Enumerable.Empty<Pig>().ToList();
            if (newList.Any() || newList.Count > 0)
                Console.WriteLine("有元素在集合中!");
            else
                Console.WriteLine("没有元素在集合中!");

 别再眼高手低了! 这些Linq方法都清楚地掌握了吗?

Except的使用  生成两个序列的差集

 List<int> list01 = new List<int> { 88, 66, 99, 58, 85, 69 };
            List<int> list02 = new List<int> { 78, 22, 69, 80, 88 };

            var newlist01 = list01.Except(list02);
            var newlist02 = list02.Except(list01);

            Console.WriteLine("以list01为准: " + string.Join(", ", newlist01));
            Console.WriteLine("以list02为准: " + string.Join(", ", newlist02));

 别再眼高手低了! 这些Linq方法都清楚地掌握了吗?

First、FirstOrDefault 的使用返回序列中的第一个元素 如果 source 不包含任何元素,则该方法将引发异常。

 //若要改为在源序列为空时返回默认值,请使用 FirstOrDefault 方法。

 int[] numbers = { 9, 34, 65, 92, 87, 435, 3, 54 };
            int first = numbers.First();
            Console.WriteLine("第一个是:" + first);
            Console.WriteLine("大于500的是:" + numbers.FirstOrDefault(c => c > 500));//带条件筛选

 别再眼高手低了! 这些Linq方法都清楚地掌握了吗?别再眼高手低了! 这些Linq方法都清楚地掌握了吗?

Group 的使用 分组,这个相对于其他已经简绍的Linq方法稍微复杂些,

List<Person> plist = new List<Person> {
                new Person{ Name="小张",Age=22,Country="中国",Sex=""},
                new Person{ Name="小郑",Age=21,Country="中国",Sex=""},
                new Person{ Name="Zhang",Age=32,Country="English",Sex=""},
                new Person{ Name="Jason",Age=29,Country="English",Sex=""},
                new Person{ Name="Luce",Age=21,Country="USA",Sex=""},
                new Person{ Name="Peter",Age=22,Country="English",Sex=""},
                new Person{ Name="Tom",Age=32,Country="English",Sex=""},
                new Person{ Name="小红",Age=28,Country="中国",Sex=""},
                new Person{ Name="小钟",Age=31,Country="中国",Sex=""}
            };

           // 按照国家来分组 1

            var plistGroupByCountry = plist.GroupBy(c => c.Country).Select(c => c).ToList();
            for (int i = 0; i < plistGroupByCountry.Count; i++)
            {
                string key = plistGroupByCountry[i].Key;
                Console.WriteLine($"按照【key={key}分组】下面对应的具体信息有:");
                var obj = plistGroupByCountry[i].ToList();
                Console.WriteLine("key=" + key + ",==>" + string.Join(",", obj.Select(c => c.Name)));
                Console.WriteLine();
            }

            //按照国家以及性别来分组 2
            var plistGroupByCountry = plist.GroupBy(c => new { c.Country, c.Sex }).Select(c => c).ToList();
            for (int i = 0; i < plistGroupByCountry.Count; i++)
            {
                string key1 = plistGroupByCountry[i].Key.Country;
                string key2 = plistGroupByCountry[i].Key.Sex;

                Console.WriteLine($"按照【key={key1}和{key2}分组】下面对应的具体信息有:");
                var obj = plistGroupByCountry[i].ToList();
                Console.WriteLine("国家分别是:" + string.Join(",", obj.Select(c => c.Country)) + "," + "姓名分别是:" + string.Join(",", obj.Select(c => c.Name)) + "性别分别是:" + string.Join(",", obj.Select(c => c.Sex)));
                Console.WriteLine();
            }

            //按照linq to object方法来分组 3
            var newlist = (from g in plist
                           group g by new { g.Country, g.Sex } into d
                           select new
                           {
                               d.Key.Country,
                               d.Key.Sex,
                               totalCountryCount = d.Count()
                           }).ToList();
            if (newlist != null && newlist.Any())
            {
                for (int i = 0; i < newlist.Count; i++)
                {
                    string key_country = newlist[i].Country;
                    string key_sex = newlist[i].Sex;
                    var groupobj = plist.Where(c => c.Country == key_country && c.Sex == key_sex).ToList();
                    if (groupobj != null && groupobj.Any())
                    {
                        Console.WriteLine("============Country:{0}===Sex:{1}====================", key_country, key_sex);
                        for (int y = 0; y < groupobj.Count; y++)
                        {
                            Console.WriteLine("name:" + groupobj[y].Name + ", age=" + groupobj[y].Age + ", Country=" + key_country + ", Sex=" + key_sex);
                        }
                    }
                    Console.WriteLine();
                }
            }
            Console.WriteLine();

            //Linq的Group 分组进一步延伸,来获取更多的信息
            var newlist = (from g in plist
                           group g by new { g.Country, g.Sex } into d
                           select new
                           {
                               d.Key.Country,
                               d.Key.Sex,
                               totalCountryCount = d.Count(),
                               maxAge = d.Max(c => c.Age),
                               minAge = d.Min(c => c.Age),
                               sumAge = d.Sum(c => c.Age),
                               //获取更多的信息,不止只有 max,min,sum,avg那些聚合函数
                               info = (from t in d
                                       join c in plist on new { t.Country, t.Sex } equals new { c.Country, c.Sex } into tgdata
                                       from td in tgdata.DefaultIfEmpty()
                                       select new { td.Name, td.Age }).Distinct().ToList()
                           }).ToList();
            for (int g = 0; g < newlist.Count; g++)
            {
                string country = newlist[g].Country; string Sex = newlist[g].Sex;
                int totalCountryCount = newlist[g].totalCountryCount;
                int maxAge = newlist[g].maxAge; int minAge = newlist[g].minAge; int sumAge = newlist[g].sumAge;
                var info = newlist[g].info;
                Console.WriteLine("============{0}======{1}==============", country, Sex);
                for (int i = 0; i < info.Count; i++)
                {
                    string name = info[i].Name;
                    int age = info[i].Age;
                    Console.WriteLine($"country={country},Sex={Sex},totalCountryCount={totalCountryCount},maxAge={maxAge},minAge={minAge},sumAge={sumAge},name={name},age={age}");
                }
                Console.WriteLine();
            }

 别再眼高手低了! 这些Linq方法都清楚地掌握了吗?别再眼高手低了! 这些Linq方法都清楚地掌握了吗?

别再眼高手低了! 这些Linq方法都清楚地掌握了吗?

 GroupJoin的使用 基于键值等同性将两个序列的元素进行关联,并对结果进行分组

 /*
             public static System.Linq.IQueryable<TResult> GroupJoin<TOuter,TInner,TKey,TResult> (this System.Linq.IQueryable<TOuter> outer, System.Collections.Generic.IEnumerable<TInner> inner, System.Linq.Expressions.Expression<Func<TOuter,TKey>> outerKeySelector, System.Linq.Expressions.Expression<Func<TInner,TKey>> innerKeySelector, System.Linq.Expressions.Expression<Func<TOuter,System.Collections.Generic.IEnumerable<TInner>,TResult>> resultSelector);
             */

            List<Student> stulist = new List<Student> {
                new Student{ sid="S001",sName="小张",bookid="bk001"},
                new Student{ sid="S002",sName="小刘",bookid="bk002"},
                new Student{ sid="S003",sName="小郑",bookid="bk003"},
                new Student{ sid="S004",sName="小李",bookid="bk004"},
                new Student{ sid="S005",sName="小赵",bookid="bk002"},
                new Student{ sid="S006",sName="小王",bookid="bk005"}
            };
            List<Book> blist = new List<Book> {
                new Book{ bid="bk001",bName="西游记"},
                new Book{ bid="bk002",bName="红楼梦"},
                new Book{ bid="bk003",bName="三国演义"},
                new Book{ bid="bk004",bName="天龙八部"},
                new Book{ bid="bk005",bName="笑傲江湖"}
            };
            var groupjoinList = stulist.GroupJoin(blist, s => s.bookid, b => b.bid, (s, _bist) => new
            {
                s.sid,
                s.sName,
                //  必需要有一个字段来接收
                booksInfo = _bist.Select(b => new
                {
                    b.bid,
                    b.bName
                }).ToList()
            }).ToList();

            for (int i = 0; i < groupjoinList.Count; i++)
            {
                string sid = groupjoinList[i].sid;
                string sname = groupjoinList[i].sName;
                var bookinfo = groupjoinList[i].booksInfo;
                Console.WriteLine("======={0}=={1}==========", sid, sname);
                for (int b = 0; b < bookinfo.Count; b++)
                {
                    string bid = bookinfo[b].bid;
                    string bname = bookinfo[b].bName;
                    Console.WriteLine($"sid={sid},sname={sname},bid={bid},bname={bname}");
                }
                Console.WriteLine();
            }

别再眼高手低了! 这些Linq方法都清楚地掌握了吗?

Intersect的使用 生成两个序列的交集,这个比较简单,很好理解

int[] list01 = { 10, 2, 58, 66, 30, 24, 56 };
            int[] list02 = { 22, 30, 86, 50, 10, 99, 64, 32, 45, 2 };

            var newlist = list01.Intersect(list02);
            foreach (var item in newlist)
                Console.WriteLine($"交集有:{item}");

            Console.WriteLine("====================");
            List<Book> blist001 = new List<Book> {
                new Book{ bid="bk001",bName="西游记"},
                new Book{ bid="bk002",bName="红楼梦"},
                new Book{ bid="bk003",bName="三国演义"},
                new Book{ bid="bk004",bName="天龙八部"},
                new Book{ bid="bk005",bName="笑傲江湖"}
            };
            List<Book> blist002 = new List<Book> {
                new Book{ bid="bk001",bName="西游记"},
                new Book{ bid="bk002",bName="红楼梦"},
                new Book{ bid="bk003",bName="三国演义"}
            };
            var newbookList = blist001.Intersect(blist002);
            if (newbookList != null && newbookList.Any())
            {
                foreach (var bookinfo in newbookList)
                    Console.WriteLine($"交集有:bid={bookinfo.bid},bName={bookinfo.bName}");
            }
            else
            {
                Console.WriteLine("没有找到,原因:是不相同的Book对象,值相同也是不行的!");
            }
            Console.WriteLine("======我们 可以通过如下方法来查询到相同的交集==============");

            var haveSameEntityList = blist001.Where(c => blist002.Exists(q => q.bid == c.bid)).ToList();
            foreach (var item in haveSameEntityList)
                Console.WriteLine($"交集有:bid={item.bid},bName={item.bName}");

 别再眼高手低了! 这些Linq方法都清楚地掌握了吗?别再眼高手低了! 这些Linq方法都清楚地掌握了吗?

Join的使用 这个我们是经常使用到的,多个集合联合查询 基于匹配键对两个序列的元素进行关联。相对于SQL中的多表联合查询,只是内连接的效果

/*
             Join<TOuter,TInner,TKey,TResult>(IQueryable<TOuter>, IEnumerable<TInner>, Expression<Func<TOuter,TKey>>, Expression<Func<TInner,TKey>>, Expression<Func<TOuter,TInner,TResult>>)
             */
            List<Book> bleft = new List<Book> {
                new Book{ bid="bk001",bName="西游记"},
                new Book{ bid="bk002",bName="红楼梦"},
                new Book{ bid="bk003",bName="三国演义"},
                new Book{ bid="bk004",bName="天龙八部"},
                new Book{ bid="bk005",bName="笑傲江湖"}
            };
            List<Book> bright = new List<Book> {
                new Book{ bid="bk001",bName="西游记"},
                new Book{ bid="bk002",bName="红楼梦"},
                new Book{ bid="bk003",bName="三国演义"}
            };
            //想象一想是:左连接
            var _Llist = bleft.Join(bright, L => L.bid, R => R.bid, (L, R) => new { L.bid, L.bName }).ToList();
            foreach (var item in _Llist)
                Console.WriteLine($"左连接:bid={item.bid},bName={item.bName}");
            Console.WriteLine("===================");
            //想象一想是:右连接,我们交换一下位置看看
            var Rlist = bright.Join(bleft, L => L.bid, R => R.bid, (L, R) => new { R.bid, R.bName }).ToList();
            foreach (var item in Rlist)
                Console.WriteLine($"右连接:bid={item.bid},bName={item.bName}");
            //内连接
            Console.WriteLine("从上面的结果可以看出 join就是内连接的效果,那左右连接要怎么实现???告示宝宝,答案!");
            //请参考个人里外一遍笔记,这里就不在重复列出:参考地址: https://www.cnblogs.com/Fengge518/p/13543250.html

 别再眼高手低了! 这些Linq方法都清楚地掌握了吗?

Last的使用 返回序列中的最后一个元素。使用起来还是比较简单!

  int[] listint = { 66, 55, 2, 88, 10, 8, 62, 5, 66, 47, 65 };
                int last = listint.Last();
                Console.WriteLine("最后一位是:" + last);

 别再眼高手低了! 这些Linq方法都清楚地掌握了吗?

LastOrDefault的使用 返回序列中的最后一个元素;如果未找到该元素,则返回默认值,测试同上

 int[] listint = { 66, 55, 2, 88, 10, 8, 62, 5, 66, 47, 65 };
                int last = listint.LastOrDefault();
                int newlast = listint.Where(c => c > 1000).LastOrDefault();
                Console.WriteLine("last最后一位是:" + last);
                Console.WriteLine("newlast最后一位是:" + newlast);

Reverse 的使用 反转序列中元素的顺序。

 List<string> liststr = new List<string> { "I", "Love", "You" };
            Console.WriteLine(string.Join(" ", liststr));
            Console.WriteLine("===========开始反转===========");
            liststr.Reverse();
            Console.WriteLine(string.Join(" ", liststr));

 别再眼高手低了! 这些Linq方法都清楚地掌握了吗?

Repeat的使用 生成包含一个重复值的序列。我们可以从字面上猜出,重复的含义

   IEnumerable<string> repeatStr = Enumerable.Repeat("我热爱学习!", 6);
            foreach (var item in repeatStr)
            {
                Console.WriteLine(item);
            }

 别再眼高手低了! 这些Linq方法都清楚地掌握了吗?

Select的使用 将序列中的每个元素投影到新表单 投影

  int[] studentAges = { 18, 16, 17, 16, 22, 30, 19, 26, 33 };
            var list = studentAges.Where(c => c >= 18).Select(c => new { info = "成年的年龄有(>=18岁): " + c }).ToList();
            foreach (var obj in list)
                Console.WriteLine("{0}", obj.info);

 别再眼高手低了! 这些Linq方法都清楚地掌握了吗?

SelectMany的使用 将序列的每个元素投影到一个 IEnumerable<T> 并将结果序列组合为一个 IQueryable<T> 类型的序列。

   List<StudentBookModel> models = new List<StudentBookModel>();
            models.Add(new StudentBookModel
            {
                sbid = "S001",
                sName = "鲁智深",
                booksname = new List<Book> {
                    new Book { bid = "b001", bName = "西游记" },new Book { bid = "b002", bName = "水浒传" }, new Book { bid = "b003", bName = "三国演义" }
                }
            });
            models.Add(new StudentBookModel
            {
                sbid = "S002",
                sName = "武僧",
                booksname = new List<Book> {
                    new Book { bid = "b004", bName = "笑傲江湖" }, new Book { bid = "b005", bName = "楚留香" },new Book { bid = "b006", bName = "射雕英雄传" }
                }
            });
            //--两层 for循环找出 bid=b002,和b006 的书本信息
            {
                Console.WriteLine("==========foreach / for 多层循环=============="); //方法一:foreach / for 多层循环
                foreach (var item in models)
                {
                    foreach (var book in item.booksname)
                    {
                        if ("b002".Equals(book.bid) || "和b006".Equals(book.bid))
                        {
                            Console.WriteLine("foreach / for 多层循环 找到书的信息: bid:{0}, bName:{1}", book.bid, book.bName);
                        }
                    }
                }
            }
            Console.WriteLine("=========from S in models linq to Sql写法==============="); //方法二: 像是些SQL那样,很是方便,层次也比较清晰
            {
                var booklist = (from S in models
                                from B in S.booksname
                                where new string[] { "b002", "b006" }.Contains(B.bid)
                                select new Book { bid = B.bid, bName = B.bName }).ToList();
                for (int i = 0; i < booklist.Count; i++)
                {
                    Console.WriteLine("from S in models 找到书的信息bid:{0}, bName:{1} ", booklist[i].bid, booklist[i].bName);
                }
            }
            {
                Console.WriteLine("=========SelectMany==============="); //方法三:SelectMany
                var booklist = models.SelectMany(s => s.booksname).Where(c =>
                new string[] { "b002", "b006" }.Contains(c.bid)).Select(c => new Book
                {
                    bid = c.bid,
                    bName = c.bName
                }).ToList();
                Console.WriteLine("SelectMany 找到书的信息: ", string.Join(" ", booklist));
            }

 别再眼高手低了! 这些Linq方法都清楚地掌握了吗?

SequenceEqual的使用 确定两个序列是否相等。

 Pet p1 = new Pet { Name = "Dog", Age = 2 };
                Pet p2 = new Pet { Name = "Pig", Age = 1 };
                Pet p3 = new Pet { Name = "Cat", Age = 3 };

                List<Pet> list01 = new List<Pet> { p1, p2, p3 };
                List<Pet> list02 = new List<Pet> { p1, p2, p3 };
                List<Pet> list03 = new List<Pet> { p2, p3, p1, };
                List<Pet> list04 = new List<Pet> { p1, p3 };

                bool flag01 = list01.SequenceEqual(list02);
                bool flag02 = list01.SequenceEqual(list03);
                bool flag03 = list01.SequenceEqual(list04);
                bool flag04 = list02.SequenceEqual(list03);
                Console.WriteLine($"list01.SequenceEqual(list02) => {flag01}");
                Console.WriteLine($"list01.SequenceEqual(list03) => {flag02}");
                Console.WriteLine($"list01.SequenceEqual(list04) => {flag03}");
                Console.WriteLine($"list02.SequenceEqual(list03) => {flag04}");

 别再眼高手低了! 这些Linq方法都清楚地掌握了吗?

Single   SingleOrDefault的使用 下面是官方的解释,由于比较简单,这里不再举例说明

/*
             *  SingleOrDefault<TSource>(IQueryable<TSource>)
             返回序列中的唯一元素;如果该序列为空,则返回默认值;如果该序列包含多个元素,此方法将引发异常
             */

            /*
             *  SingleOrDefault<TSource>(IQueryable<TSource>, Expression<Func<TSource, Boolean>>)
             返回序列中满足指定条件的唯一元素;如果这类元素不存在,则返回默认值;如果有多个元素满足该条件,此方法将引发异常
             */

Skip Take的使用 一起使用,分页的效果 Skip:跳过多少数据,Take拿取多少数据

 List<int> list = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
                var newlist01 = list.Skip(2).ToList();
                var newlist02 = list.Skip(2).Take(3).ToList();
                Console.WriteLine("原来的数据集合" + string.Join(" ", list));
                Console.WriteLine("list.Skip(2)=> " + string.Join(" ", newlist01));
                Console.WriteLine("list.Skip(2).Take(3)=> " + string.Join(" ", newlist02));

 别再眼高手低了! 这些Linq方法都清楚地掌握了吗?

ThenBy ThenByDescending的使用 排序时继续按照其他的字段来排序

   List<Pig> list = new List<Pig>
                {
                          new Pig{pid="p001",name="小猪",age=1 },
                          new Pig{pid="p004",name="八戒",age=500 },
                          new Pig{pid="p002",name="小八戒",age=100 },
                          new Pig{pid="p008",name="老年八戒",age=600 },
                          new Pig{pid="p003",name="青年猪",age=2 },
                          new Pig{pid="p003",name="老猪",age=10 },
                          new Pig{pid="p004",name="假八戒",age=-1 },
                          new Pig{pid="p008",name="成仙八戒",age=1000 }
                 };
                var newlist01 = list.OrderBy(c => c.pid).ToList();
                var newlist02 = list.OrderBy(c => c.pid).ThenBy(c => c.age).ToList();
                var newlist03 = list.OrderBy(c => c.pid).ThenByDescending(c => c.age).ToList();
                Console.WriteLine("===========newlist01=====按照pid从小到大排序==========");
                Console.WriteLine("pid asc排序" + string.Join(" ", newlist01.Select(c => c.pid)));
                Console.WriteLine("age asc排序:" + string.Join(" ", newlist01.Select(c => c.age)));
                Console.WriteLine();
                Console.WriteLine("===========newlist02====按照pid从小到大并且年龄从小到大排序===========");
                Console.WriteLine("pid asc排序:" + string.Join(" ", newlist02.Select(c => c.pid)));
                Console.WriteLine("age asc排序:" + string.Join(" ", newlist02.Select(c => c.age)));
                Console.WriteLine();
                Console.WriteLine("===========newlist03===按照pid从小到大并且年龄从大到小排序============");
                Console.WriteLine("pid asc排序:" + string.Join(" ", newlist03.Select(c => c.pid)));
                Console.WriteLine("age asc排序:" + string.Join(" ", newlist03.Select(c => c.age)));

别再眼高手低了! 这些Linq方法都清楚地掌握了吗?

Union 的使用 生成两个序列的并集。 类似 sql中的Unio 会去重

 int[] list01 = { 5, 6, 9, 8, 3, 1, 7 };
                int[] list02 = { 3, 6, 4, 8, 2, 5, 1, 9 };
                List<Pet> listpet01 = new List<Pet> {
                    new Pet{ Name="Dog1",Age=2},
                    new Pet{ Name="Dog2",Age=1}
                };
                List<Pet> listpet02 = new List<Pet> {
                    new Pet{ Name="cat",Age=3},
                    new Pet{ Name="pig",Age=1},
                    new Pet{ Name="bird",Age=5}
                };
                var newlist = list01.(list02);
                var newlist2 = listpet01.Union(listpet02).Select(c => c.Name).ToList();

                Console.WriteLine("数组结合unio之后:" + string.Join(" ", newlist));
                Console.WriteLine("我有如下这些宠物:" + string.Join("; ", newlist2));

 别再眼高手低了! 这些Linq方法都清楚地掌握了吗?

ToDictionary 的使用 下面为官方的扩展方法字符串

 /*
             public static System.Collections.Generic.Dictionary<TKey,TSource> ToDictionary<TSource,TKey> (this System.Collections.Generic.IEnumerable<TSource> source, Func<TSource,TKey> keySelector);
             */
            List<Person> ps = new List<Person> {
                     new Person{ Name="小张",Age=22,Country="中国",Sex=""},
                     new Person{ Name="小郑",Age=21,Country="中国",Sex=""},
                     new Person{ Name="Zhang",Age=32,Country="English",Sex=""},
                     new Person{ Name="Jason",Age=29,Country="English",Sex=""},
                     new Person{ Name="Luce",Age=21,Country="USA",Sex=""},
                     new Person{ Name="Peter",Age=22,Country="English",Sex=""},
                     new Person{ Name="Tom",Age=32,Country="English",Sex=""},
                     new Person{ Name="小红",Age=28,Country="中国",Sex=""},
                     new Person{ Name="小钟",Age=31,Country="中国",Sex=""}
               };
            Dictionary<string, int> dic1 = ps.ToDictionary(p => p.Name, a => a.Age);
            Dictionary<string, Person> dic2 = ps.ToDictionary(p => p.Name);


            foreach (KeyValuePair<string, int> item in dic1)
            {
                Console.WriteLine("key:{0},age:{1}", item.Key, item.Value);
            }
            Console.WriteLine("===============value为对象类型的数据================");
            foreach (KeyValuePair<string, Person> item in dic2)
            {
                Console.WriteLine("key:{0},age:{1},Country:{2},sex:{3}", item.Key, item.Value.Age, item.Value.Country, item.Value.Sex);
            }

 别再眼高手低了! 这些Linq方法都清楚地掌握了吗?

Sum,Min,Max,Average等的使用 这些还是比较简单,还是简单举例一下吧,看到的宝宝们是否会点个赞啊?嘻嘻

            List<decimal> listdecime = new List<decimal> { 58m, 66, 90m, 60, 88m, 70m, 99m, 76m, 83m };
            decimal maxScore = listdecime.Max();
            decimal minScore = listdecime.Min();
            decimal sumScore = listdecime.Sum();
            decimal avgScore = listdecime.Average();
            decimal avgScoreFromart = Math.Round(avgScore, 2);
            Console.WriteLine("最大分数{0},最小分数{1},总分数{2},平均分数{3},保留数字后两位小数点{4}", maxScore, minScore, sumScore, avgScore, avgScoreFromart);

 别再眼高手低了! 这些Linq方法都清楚地掌握了吗?

ToLookup的使用 从 IEnumerable<T> 生成一个泛型 Lookup<TKey,TElement>,宝宝表示没有看懂?啥东东? 我这里就给宝宝们列举一个案例demo

  List<Pig> stulist = new List<Pig> {
                new Pig{pid="P001",name="小猪1",age=1 },
                new Pig{pid="P002",name="小猪2",age=2 },
                new Pig{pid="P001",name="小猪1",age=1 },
                new Pig{pid="P002",name="小猪2",age=2 },
                new Pig{pid="P001",name="小猪1",age=1 },
                new Pig{pid="P003",name="小猪3",age=3 },
                new Pig{pid="P003",name="小猪3",age=3 },
                new Pig{pid="P001",name="小猪1",age=1 },
                new Pig{pid="P004",name="小猪4",age=4 },
                new Pig{pid="P003",name="小猪3",age=3 }
            };
            // 这里就不在输出GroupBy了,stulist.GroupBy(p => p.pid).ToList();
            List<IGrouping<string, Pig>> Luplist = stulist.ToLookup(p => p.pid).ToList();
            var newlist = stulist.ToLookup(c => c.pid, p => new { p.pid, p.name, p.age }).ToList();

            foreach (var item in Luplist)
            {
                Console.WriteLine("========key:{0}==========", item.Key);
                foreach (var info in item)
                {
                    Console.WriteLine("pid:{0}, name:{1}, age:{2}", info.pid, info.name, info.age);
                }
            }

 别再眼高手低了! 这些Linq方法都清楚地掌握了吗? 别再眼高手低了! 这些Linq方法都清楚地掌握了吗?

Zip的使用 类似拉链的效果 将指定函数应用于两个序列的对应元素,以生成结果序列,啥东东??

第一眼还以为是压缩的啥东东, 后来仔细看文档才清白,完全就不是一回事,嘻嘻!
            string[] listPerson = { "孙悟空", "猪八戒", "沙悟净", "唐三藏", "白骨精", "如来佛" };
            int[] ages = { 600, 500, 400, 1000, 300, 1100 };
            IEnumerable<(string, int)> listobj = listPerson.Zip(ages);//这里故意写出前面的类型是为了方便了返回的类型是啥
            foreach (var item in listobj)
                Console.WriteLine("姓名:{0}, 年龄:{1}", item.Item1, item.Item2);

别再眼高手低了! 这些Linq方法都清楚地掌握了吗?

6:一些使用的临时model

别再眼高手低了! 这些Linq方法都清楚地掌握了吗?别再眼高手低了! 这些Linq方法都清楚地掌握了吗?

 class Pet
        {
            public string Name { get; set; }
            public int Age { get; set; }
        }
        class Student
        {
            public string sid { get; set; }
            public string sName { get; set; }
            public string bookid { get; set; }
        }

        class StudentBookModel
        {

            public string sbid { get; set; }
            public string sName { get; set; }
            public List<Book> booksname { get; set; }
        }
        class Book
        {
            public string bid { get; set; }
            public string bName { get; set; }
        }

        class Person
        {
            public string Name { get; set; }
            public int Age { get; set; }
            public string Country { get; set; }
            public string Sex { get; set; }
        }

        class MyDog<T> : List<T>
        {
            public IEnumerable<T> MyWhere(Func<T, bool> func)
            {
                return Enumerable.Where(this, func);
            }
        }

        class Pig
        {
            public string pid { get; set; }
            public string name { get; set; }
            public int age { get; set; }
        }

View Code

 7:好了,先到这里,欢迎大家留言,指教,谢谢

 


喜欢 (0)