• 第十六节:Linq用法大全(四)


    1. OfType

       获取集合中中指定类型元素。

     object[] obj = { 1, 23, 4, 5, 555, "aaa", "bbb" };
     int max = obj.OfType<int>().Max();  //结果是55, 获取int类型中的最大值

    2. selectMany

      相当于二次遍历查找,先遍历一级出来item,再遍历二级item. 和Select的区别,Select只遍历一级。

                string[] text = { "Albert was here", "Burke slept late", "Connor is happy" };
                var d1 = text.Select(s => s.Split(' ')).ToList();   //3个元素,每个元素里面又有3个
                var d2 = text.SelectMany(s => s.Split(' ')).ToList();   //9个元素
                var d3 = text.Select(s => s.ToString()).ToList();   //3个元素
                var d4 = text.SelectMany(s => s.ToString()).ToList();   //45个元素,一个字母一个元素,空格也算
                foreach (var item in d4)
                {
                    Console.WriteLine(item);
                }

    3. GroupJoin

      类似sql中的左连接,linq中join-on-into, 注意:linq中的做外链接操控数据库和直接查出来的集合是不一样,参考集合select的时候要判空,详见下面代码。

    代码分享:

     1   List<Person> pList = new List<Person>
     2             {
     3                 new Person{ id = 1, pName = "ABC" },
     4                 new Person{ id = 2, pName = "EFG" },
     5                 new Person{ id = 3, pName = "HIJ"},
     6                 new Person{ id = 4, pName = "KLM"},
     7                 new Person{ id = 5, pName = "NOP" },
     8                 new Person{ id = 6, pName = "QRS"},
     9                 new Person{ id = 7, pName = "TUV"}
    10             };
    11             List<City> cList = new List<City>
    12             {
    13                 new City{ id = 1,cName = "Guangzhou",uId=1},
    14                 new City{ id = 2,cName = "Shenzhen",uId=2 },
    15                 new City{ id = 3,cName = "Beijing" ,uId=3},
    16                 new City{ id = 4,cName = "Shanghai",uId=4 },
    17                 new City{ id = 8,cName = "K4",uId=4 }
    18             };
    19             //3.1 先用linq实现一下左连接
    20             ////左外连接,需要对右表进行判空 
    21             ////此处需要特别注意:这里是对应已经查出来的集合进行左外链接,所以需要对右表进行判空处理,如:cName = k == null ? "" : k.cName
    22             ////但是这里如果改成直接操作数据库,pList改为db.Person,cList改为db.City, 则无需对右表进行判空,因为它会生成标准left join的sql语句,操控数据库。
    23            Console.WriteLine("------------------------下面是linq左连接查询--------------------------");
    24             var result1 = from p in pList
    25                           join c in cList on p.id equals c.uId into fk
    26                           from k in fk.DefaultIfEmpty()
    27                           select new { p.id, p.pName, cName = k == null ? "" : k.cName };
    28             var list1 = result1.ToList();
    29             foreach (var item in list1)
    30             {
    31                 Console.WriteLine($"UserId={item.id},Name={item.pName},CityName={item.cName}");
    32             }
    33             //3.2  重点GroupJoin用法 (等价于上面的左外连接)
    34             Console.WriteLine("------------------------下面是GroupJoin左连接查询--------------------------");
    35             var result2 = pList.AsQueryable().GroupJoin(cList, p => p.id, c => c.uId, (p, cs) => new
    36             {
    37                 p.id,
    38                 p.pName,
    39                 cName = cs.Select(u => u.cName).ToList()
    40             });
    41             var list2 = result2.ToList();
    42             foreach (var item in list2)
    43             {
    44                 if (item.cName.Count() != 0)
    45                 {
    46                     foreach (var citem in item.cName)
    47                     {
    48                         Console.WriteLine($"CityID={item.id},Name={item.pName},CityName={citem}");
    49                     }
    50                 }
    51                 else
    52                 {
    53                     Console.WriteLine($"CityID={item.id},Name={item.pName},CityName=");
    54                 }
    55             }

    运行结果:

    4. ToLookup

      当同一个key要求对应多个value情况ToLookup方法是非常有用的,ToLookup返回一种特殊的数据结构类似我们sql中的group.可以把集合分组并且可以用索引访问这些元素。

    注意: Lookup,不像Dictionary, 是不可改变的。 这意味着一旦你创建一个lookup, 你不能对数据源添加或删除元素,即无效,GroupBy后是可以增删的

                var products = new List<Product>
                                   {
                                       new Product {pId = "1", Category = "Electronics", Value = 15.0},
                                       new Product {pId = "2", Category = "Groceries", Value = 40.0},
                                       new Product {pId = "3", Category = "Garden", Value = 210.3},
                                       new Product {pId = "4", Category = "Pets", Value = 2.1},
                                       new Product {pId = "5", Category = "Electronics", Value = 19.95},
                                       new Product {pId = "6", Category = "Pets", Value = 21.25},
                                       new Product {pId = "7", Category = "Pets", Value = 5.50},
                                       new Product {pId = "8", Category = "Garden", Value = 13.0},
                                       new Product {pId = "9", Category = "Automotive", Value = 10.0},
                                       new Product {pId = "10", Category = "Electronics", Value = 250.0},
                                   };
    
                {
                    Console.WriteLine("使用ToLookup分组");
                    var groups = products.ToLookup(p => p.Category);
                    //删除所有属于Garden的产品(注意ToLookup删除无效哦)
                    products.RemoveAll(p => p.Category == "Garden");
                    foreach (var group in groups)
                    {
                        Console.WriteLine(group.Key);
                        foreach (var item in group)
                        {
                            Console.WriteLine($"pid={item.pId},Category={item.Category},Value={item.Value}");
                        }
                    }
                }
                {
                    Console.WriteLine("使用GroupBy分组");
                    var groups = products.GroupBy(p => p.Category);
                    //删除所有属于Garden的产品
                    products.RemoveAll(p => p.Category == "Garden");
                    foreach (var group in groups)
                    {
                        Console.WriteLine(group.Key);
                        foreach (var item in group)
                        {
                            Console.WriteLine($"pid={item.pId},Category={item.Category},Value={item.Value}");
                        }
                    }
                }

    运行结果:

    5. AsEnumerable/AsQueryable/Cast

    (1).AsEnumerable:是延迟执行的,实际上什么都没有发生,当真正使用对象的时候才执行.

    (2).AsQueryable:也是延迟执行的,将一个序列向下转换为一个IQueryable, 它生成了一个本地查询的IQueryable包装.

    下面看一下各自linq生成的SQL语句:

     

     

    (3).Cast:将 IQueryable 的元素转换为指定的类型

                List<object> words = new List<object> { "green", "blue", "violet" };
                var query1 = words.AsQueryable().Cast<string>().ToList();   //将object类型的list集合转换成string的list集合
                //补充写法2
                List<string> query = words.Select(u => (string)u).ToList();  //实际上遍历挨个转换

    6. SequenceEqual

      比较list和list之间、数组和数组之间是否相等。

                string[] text1 = { "Albert was here", "Burke slept late", "Connor is happy" };
                string[] text2 = { "Albert was here", "Burke slept late", "Connor is happy" };
                string[] text3 = { "Albert was here", "Burke slept late", "Connor is happy111" };
                string[] text4 = { "Albert was here", "Burke slept late" };
                Console.WriteLine(text1.SequenceEqual(text2));   //true
                Console.WriteLine(text2.SequenceEqual(text3));   //false
                Console.WriteLine(text2.SequenceEqual(text4));   //false

    7. DefaultIfEmpty

      返回指定序列的元素;如果序列为空,则返回单一实例集合中的类型参数的默认值。多用于外连接查询。

                int[] arr1 = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };//构造带元素的数组
                int[] arr2 = { }; //构造一个空数组
                string[] str = { };
                var d1 = arr1.DefaultIfEmpty().ToList();   //9个元素
                var d2 = arr2.DefaultIfEmpty().ToList();   //1个元素,且为0,即int类型的默认值
                var d3 = arr2.DefaultIfEmpty(86).ToList(); //1个元素,且为86,即int类型的默认值
                var d4 = str.DefaultIfEmpty().ToList();    //1个元素,且为null,即string类型的默认值

    8. Empty

      内部生成了一个T[]数组,数组的个数为0。

                List<string> list1 = new List<string>();
                var arry2 = Enumerable.Empty<string>();  //Enumerable.Empty<int>() 其实在内部生成了一个T[]数组,数组的个数为0。
                foreach (var item in list1)
                {
                    Console.WriteLine(item);
                }
                foreach (var item in arry2)
                {
                    Console.WriteLine(item);
                }

    9. Range

      生成指定范围内的整数的序列。如下代码:

                var list = Enumerable.Range(10, 100).ToList();  //从10开始,依次添加100个整数,即 10-109
                foreach (var item in list)
                {
                    Console.WriteLine(item);
                }

    10.Repeat

      包含一个重复值的序列。

                var list = Enumerable.Repeat<int>(10, 100).ToList();   //生成100个10存放在集合中
                foreach (var item in list)
                {
                    Console.WriteLine(item);
                }

    11.Aggregate

      做一些复杂的聚合运算,例如累计求和,累计求乘积。它接受2个参数,一般第一个参数是称为累积数(默认情况下等于第一个值),而第二个代表了下一个值。第一次计算之后,计算的结果会替换掉第一个参数,继续参与下一次计算,第二个参数往后顺延。

                {
                    //11.1 累加和阶乘
                    int[] arry1 = { 1, 2, 3, 4, 5 };
                    int result1 = arry1.Aggregate((a, b) =>
                    {
                        return a + b;
                    });
                    //执行的操作是: 1+2=3; 3+3=6; 6+4=10; 10+5=15;
                    Console.WriteLine($"累加的结果为:{result1}");
                    int result2 = arry1.Aggregate((a, b) =>
                    {
                        return a * b;
                    });
                    //执行的操作是: 1*2=2; 2*3=6; 6*4=24; 24*5=120;
                    Console.WriteLine($"阶乘的结果为:{result2}");
                    //11.2. 实现字符串翻转
                    string msg1 = "my name is ypf";
                    string[] arry3 = msg1.Split(' ');
                    string result3 = arry3.Aggregate((m, n) =>
                    {
                        return $"{n} {m}";
                    });
                    Console.WriteLine($"反转后的结果为:{result3}");
                    //11.3 求数组中比“banana”长度长的最长字符串
                    string[] fruits = { "apple", "mango", "orange", "passionfruit", "grape" };
                    // Determine whether any string in the array is longer than "banana".
                    string longestName = fruits.Aggregate("banana", (longest, next) =>
                    {
                        return next.Length > longest.Length ? next : longest;
                    }, fruit => fruit.ToLower());
    
                    Console.WriteLine("The fruit with the longest name is {0}.", longestName);
                }

    运行结果:

     

    !

    • 作       者 : Yaopengfei(姚鹏飞)
    • 博客地址 : http://www.cnblogs.com/yaopengfei/
    • 声     明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
    • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
     
  • 相关阅读:
    环形二维数组
    梦断代码(三)
    梦断代码(二)
    梦断代码(一)
    CNblogs用户体验
    《软件工程》--读书笔记三
    《软件工程》--读书笔记二
    《软件工程》--读书笔记一
    找出水王
    典型用户
  • 原文地址:https://www.cnblogs.com/yaopengfei/p/12259731.html
Copyright © 2020-2023  润新知