• linq总结系列(一)---基础部分


    一、linq的基本概念

      LINQ是C#和VB中的统一查询语法,使用对象来保存和检索来自不同来源(如数据库、xml、对象集合)的数据。

      主要功能:消除了编程语言和数据库之间的不匹配,以及为不同类型的数据源提供统一的查询接口。

      适用范围:LInq适用于实现了IEnumerable <T>(IQueryable继承于IEnumerable )的实例,如:List,Dictionary,Queue,LinkedList,Array等

    二、linq的使用

      有两种方法可以将LINQ查询写入IEnumerable集合或IQueryable数据源。

      1、查询语法

        特点:以from子句开头,可以以select或groupBy子句结束

      2、lambda表达式(简洁且功能更多,推荐)

      下边给出了简单的例子,注:后边的部分都是使用的这个测试数据。

     1   //准备的测试数据
     2             IList<UserInfo> userList = new List<UserInfo>() { 
     3                  new UserInfo() { UId = 1, UserName = "zs", Age = 23 ,RoleId=1} ,
     4                  new UserInfo() { UId = 2, UserName = "ls", Age = 20 ,RoleId=2},
     5                  new UserInfo() { UId = 3, UserName = "ww", Age = 33 ,RoleId=1},
     6                  new UserInfo() { UId = 4, UserName = "zl", Age = 26 ,RoleId=2},
     7                  new UserInfo() { UId = 5, UserName = "tq", Age = 42 ,RoleId=2} 
     8               };//用户列表
     9             IList<RoleInfo> roleList = new List<RoleInfo>(){
    10                 new RoleInfo(){Rid=1,RoleName="管理员"},
    11                 new RoleInfo(){Rid=2,RoleName="普通用户"},
    12             };//角色列表
    13 
    14             //query语法
    15             var resUsers = from u in userList
    16                            where u.Age > 20
    17                            select new {u.UId,u.UserName,u.Age};
    18             //lambda
    19             var resUsers2 = userList.Where<UserInfo>(u => u.Age > 20).Select
                      (u => new { u.UId,u.UserName,u.Age});

    三、linq详解

    1、过滤 (where 和 oftype)

      Where:根据给定的条件表达式过滤集合,并返回一个新集合

      OfType:根据类型进行过滤

    1        IList<object> list = new List<object>() { 1, "hello", user };//user是一个UserInfo的实例
    2             //query语法
    3               var result = from o in list.OfType<string>()
    4                            select o;
    5             //lambda语法
    6               var result2 = list.OfType<string>();

    2、排序(OrderBy,OrderByDescending,ThenBy,ThenByDescending)

    1     //对userList先按Id排序,再按Age排序
    2             //query语法
    3             var result = from u in userList
    4                          orderby u.Id,u.Age descending
    5                          select u;
    6             //lambda语法  
    7             var result2 = userList.OrderByDescending(u => u.Id).ThenBy(u=>u.Age);

    3、分组(group by,ToLookUp)

           //query语法
                  var resGroups = from u in userList
                                  group u by u.RoleId;
             //lambda方式  注:GroupBy延迟执行,而ToLookup是立即执行的,使用方法和GroupBy一样。
                  var resGroups2 = userList.GroupBy(u => u.RoleId);
                  //遍历(group.Key为设置分组的列的值)
                 foreach (var group in resGroups)
                  {
                      Console.WriteLine("roleId:{0}", group.Key);
                     foreach (UserInfo user in group)
                     {
                        Console.WriteLine("UserName:{0}", user.UserName);
                     }
                 }
                 /*结果:  roleId:1
                         UserName:zs
                         UserName:ww
                         roleId:2
                         UserName:ls
               UserName:zl 21  UserName:tq */
        
    //多列分组
        var productGroup=
            from p in db.Products
            group p by new
            {
                p.PName,
                p.PColor
            }
            into g
            select new
                    {
                        g.Key,//这里的key是一个对象,有两个属性:PName,PColor
                        g
                    };
     

    4、连接查询(join)

       //query语法,查询用户名和该用户所属的角色 inner join
                 var resJoin = from user in userList
                               join role in roleList
                              on user.RoleId equals role.Rid
                              select new
                               {
                                   uname=user.UserName,
                                  rname=role.RoleName
                               };
     
        //left join,right join调整下顺序即可
        var resJoin = from user in userList
                              join role in roleList
                              on user.RoleId equals role.Rid into temp
                    from tt in temp.DefaultIfEmpty
                               select new
                              {
                                  uname=user.UserName,
                                  rname=role?.RoleName
                               };
        //cross join
        var resJoin = from user in userList
                            from role in roleList
                                   select new
                                  {
                                      uname=user?.UserName,
                                      rname=role?.RoleName
                                  };
    
             //lambda方式
                 var resJoin2 = userList.Join(roleList, 
                     user => user.RoleId,  //outkey
                     role => role.Rid,     //innerkey
                     (user, role) => new   //result
                     {
                         uname = user.UserName,
                         rname = role.RoleName
                     });
                 //遍历
                 foreach (var item in resJoin2)
                 {
                     Console.WriteLine("用户:{0}----角色:{1}", item.uname, item.rname);
                 }
     
                 /*结果:  用户:zs----角色:管理员
                         用户:ls----角色:普通用户
                         用户:ww----角色:管理员
                         用户:zl----角色:普通用户
                         用户:tq----角色:普通用户 */

    5、linq中的量词(All,Any,Contains)

     1     //All 所有元素都符合条件返回true 
     2             bool areAllAdmin = userList.All(u => u.RoleId == 1);   //所有用户的roleid都是1--->false
     3       //Any 有一个符合条件就返回true
     4             bool isAnyAdmin = userList.Any(u => u.RoleId == 1);//用户里有没有roleid为1的 --> true
     5       //Contains 包含返回true
     6             UserInfo user1=new UserInfo() { UId = 1, UserName = "zs", Age = 23, RoleId = 1 };
     7             //contains比较的是索引,所以就是list中有一个属性都相同的元素也会返回false,我们可以自定义一个比较类CompareUser来解决这个问题
     8             bool isContains = userList.Contains(user1);//s索引不同:false
     9             bool isContains2=userList.Contains(user1,new CompareUser());//自定义比较:true
    10 
    11 //自定义的userinfo比较器
    12     public class CompareUser : IEqualityComparer<UserInfo>
    13     { 
    14         public bool Equals(UserInfo x, UserInfo y)
    15         {
    16             bool isSame = false;
    17             //age,username,roleid相同,我们就认为是同一个userinfo
    18             if (x.Age==y.Age&&x.UserName==y.UserName&&x.RoleId==y.RoleId)
    19             {
    20                 isSame=true;
    21             }
    22             return isSame;
    23         }
    24         public int GetHashCode(UserInfo obj)
    25         {
    26             throw new NotImplementedException();
    27         }
    28     }

    6、聚合函数(Average,Count,Max,Min,Sum) 

     1   //平均年龄:28.8
     2             var avgAge = userList.Average(u => u.Age);
     3    //用户人数:5:  大于30岁的用户人数:2
     4             var userCount = userList.Count();
     5             var olduserCount = userList.Count(u => u.Age > 30);
     6    //最大年龄:42
     7             var maxAge = userList.Max(u => u.Age);
     8    //最小年龄:20
     9             var minAge = userList.Min(u => u.Age);
    10    //年龄和:144
    11             var sumAge = userList.Sum(u => u.Age);

    7、元素操作符(ElementAt,Frist,Last,Singe和对应的xxxOrDefault)

        这些操作符加上OrDefault后缀后,在超出索引时不会抛出异常,而是返回一个默认值,(如:int返回0 ,引用类型返回null)

     1     //获取指定索引处的元素
     2             UserInfo user0 = userList.ElementAt(0);
     3             UserInfo user9 = userList.ElementAtOrDefault(9);
     4             //不报错,返回null,没有ordefault后缀会抛异常
     5        //获取第一个元素
     6             UserInfo userfrist = userList.First();
     7             UserInfo userfrist2 = userList.FirstOrDefault();
     8        //获取最后一个元素
     9             UserInfo userlast = userList.Last();
    10             UserInfo userlast2 = userList.LastOrDefault();
    11        //获取唯一元素()
    12             UserInfo userSignal = userList.Single(u => u.Age < 21);
    13             UserInfo userSignal2 = userList.SingleOrDefault(u => u.Age > 21);
             //报错,返回的元素不是唯一的

    8、判断序列相等(SequenceEqual)

     1  //原始类型(字符串、int等,比较顺序和值,这两项都相等时返回true)
     2             IList<int> intList1 = new List<int> { 1, 2, 3, 4 };
     3             IList<int> intList2 = new List<int> { 2, 1, 3, 4 };
     4             //bool isEquel = intList1.SequenceEqual(intList2);
     5 
     6 //复杂类型(UserInfo,比较索引,索引相同返回true,可通过自定义比较器修改比较的规则)
     7             UserInfo user1 = new UserInfo() { UId = 1, UserName = "zs", Age = 23, RoleId = 1 };
     8             UserInfo user2 = new UserInfo() { UId = 1, UserName = "zs", Age = 23, RoleId = 1 };
     9             IList<UserInfo> list1 = new List<UserInfo>() { user1 };
    10             IList<UserInfo> list2 = new List<UserInfo>() { user2};
    11             //user1和user2的索引不同,返回false
    12             bool isEquel = list1.SequenceEqual(list2);
    13             //自定义比较器,只要属性都相等返回true
    14             bool isEquel2 = list1.SequenceEqual(list2, new CompareUser());
    15             
    16 
    17     //自定义的userinfo比较器
    18     public class CompareUser : IEqualityComparer<UserInfo>
    19     { 
    20         public bool Equals(UserInfo x, UserInfo y)
    21         {
    22             bool isSame = false;
    23             //age,username,roleid相同,我们就认为是同一个userinfo
    24             if (x.Age==y.Age&&x.UserName==y.UserName&&x.RoleId==y.RoleId)
    25             {
    26                 isSame=true;
    27             }
    28             return isSame;
    29         }
    30         public int GetHashCode(UserInfo obj)
    31         {
    32             throw new NotImplementedException();
    33         }
    34     }

    9、集合操作(Concat、Distinct、Except、Intersect、Union) 

     1      //合并 Concat
     2             IList<UserInfo> list1 = new List<UserInfo>() { user1,user2,user1 };
     3             IList<UserInfo> list2 = new List<UserInfo>() { user2 ,user2};
     4             var listConcat = list1.Concat(list2);
            //包含了user1,user2,user1,user2,user2 5 //去重 Distinct(差并交集会自动去重,去重和交差并集中的复杂类型也是根据索引来判断是否相同的,所以视情况自定义比较器) 6 var list4 = list1.Distinct();//user1,user2 7 //差集(list1中有,list中没有的) 8 var list5 = list1.Except(list2);//user1 9 //交集 10 var list6 = list1.Intersect(list2);//user2 11 //并集 12 var list7 = list1.Union(list2);//user1,user2

    10、分区(Skip,SkipWhile,Take,TakeWhile)

    1      //分区           
    2             var resUsers = userList.Skip(2);//跳过前2条,返回从第3条到最后一条的记录
    3             var resUsers2 = userList.SkipWhile(u => u.Age < 30); // 跳过满足条件的数据 
    4             //结果:从年龄为33的开始,返回后几条
    5 
    6             var resTake = userList.Take(2);//取前2条数据
    7             var resTake2 = userList.TakeWhile(u => u.Age >= 22);
    8             //取满足条件的数据,如果连续几条都满足返回多条记录,直到某一条数据不满足条件  
    9             //结果:返回第一条,如果把条件中22改成20,那么返回所有数据

    11、类型转化(As,To,Cast)  select 默认返回的是IEnumerable类型

    1        var users = from u in userList select u; //IEnumerable<UserInfo>
    2             var usersEnum = (from u in userList select u).AsEnumerable<UserInfo>();//IEnumerable<UserInfo>
    3             var usersCast = (from u in userList select u).Cast<UserInfo>();//IEnumerable<UserInfo>,功能和AsEnumerable一样,写着简单
    4             var usersQuery = (from u in userList select u).AsQueryable<UserInfo>();//IQueryable<UserInfo>
    5             var usersArray = (from u in userList select u).ToArray<UserInfo>();//UserInfo[]
    6             var usersList = (from u in userList select u).ToList<UserInfo>();//List<UserInfo>
    7             var usersDic = (from u in userList select u).ToDictionary<UserInfo,int>(u=>u.UId);//Dictionary<int,UserInfo>
  • 相关阅读:
    「10.10」神炎皇(欧拉函数)·降雷皇(线段树,DP)·幻魔皇
    「10.8」simple「数学」·walk「树上直径」
    10.5「嘟嘟噜」·「天才绅士少女助手克里斯蒂娜」·「凤凰院凶真」
    csp-s模拟测试59(10.4)「Reverse」(set)·「Silhouette」(容斥)
    csp-s模拟测试58「Divisors」·「Market」·「Dash Speed」
    csp-s模拟测试57(10.2)「天空龙」·「巨神兵」·「太阳神」
    csp-s模拟测试56(10.2)Merchant「二分」·Equation「树状数组」
    csp-s模拟测试55(9.29)联「线段树」·赛「??」题「神仙DP」
    消防(树上直径)
    模拟测试65
  • 原文地址:https://www.cnblogs.com/wyy1234/p/9053580.html
Copyright © 2020-2023  润新知