欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

C#之LINQ大全

最编程 2024-08-10 16:57:28
...

一、手写Linq Where方法

1.Linq前置知识:枚举器与迭代器、泛型、委托、Lambda表达式、yeild关键字、匿名方法、拓展方法、var关键字

  1. Linq的方法都是 IEnumerable<T>的扩展方法>>只要实现了 IEnumerable<T>的都可以使用Linq里面提供的扩展方法
    比如:数组、List、Dictionary、Set.....
using System;
using System.Collections.Generic;
using System.Linq;
using ConsoleApp1;
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] nums = new int[] { 7, 8, 9, 10, 11, 33, 456 };
            //默认调用Linq Where(扩展方法)
            IEnumerable<int> result = nums.Where(a => a > 10);
            foreach (var i in result)
            {
                Console.WriteLine(i);
            }
            //调用第一个自定义Where方法
            IEnumerable<int> GetNumsFromMyWhere1 = MyWhere1(nums, a => a > 10);
            /*
             *var进行类型推断等同上 IEnumerable<int>
            var GetNumsFromMyWhere1 = MyWhere1(nums, a => a > 10);
            */
            foreach (var i in GetNumsFromMyWhere1)
            {
                Console.WriteLine(i);
            }
            //调用第二个自定义Where方法
            IEnumerable<int> GetNumsFromMyWhere2 = MyWhere2(nums, a => a > 10);
            /*
            var GetNumsFromMyWhere2 = MyWhere2(nums, a => a > 10);
            */
            foreach (var i in GetNumsFromMyWhere2)
            {
                Console.WriteLine(i);
            }
        }
        static IEnumerable<int> MyWhere1( IEnumerable<int> items,Func<int,bool> f)
        {
            List<int> result = new List<int>();
            foreach (var item in items)
            {
                if (f(item))
                {
                    result.Add(item);
                }
            }
            return result;

        }

        static IEnumerable<int> MyWhere2(IEnumerable<int> items, Func<int, bool> f)
        {
            List<int> result = new List<int>();
            foreach (var item in items)
            {
                if (f(item))
                {
                    yield return item; //动态返回:处理一次返回一次,相对第一种效率更改
                }
            }

        }
    }
}

二、LINQ基础语法合集

1.常用函数:Where、Count、Any、Single、SingleOrDefault、First、OrderBy、Skip、Take、Max、Min、Select、Groupby
2.集合转换:IEnumerable<T>转换成列表或数组
3.【Linq方法语法】与【类SQL的查询语法】区别
4.常用函数的链式操作

using System;
using System.Collections.Generic;
using System.Linq;
using ConsoleApp1;
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args) 
        {
            List<Employee> List = new List<Employee>();
            List.Add(new Employee { id = 1, Name = "jerry", Age = 28, Gender = true, Salary = 5000 });
            List.Add(new Employee { id = 2, Name = "jim", Age = 33, Gender = true, Salary = 3000 });
            List.Add(new Employee { id = 3, Name = "lily", Age = 35, Gender = false, Salary = 9000 });
            List.Add(new Employee { id = 4, Name = "lucy", Age = 16, Gender = false, Salary = 2000 });
            List.Add(new Employee { id = 5, Name = "kimi", Age = 25, Gender = true, Salary = 1000 });
            List.Add(new Employee { id = 6, Name = "nancy", Age = 35, Gender = false, Salary = 8000 });
            List.Add(new Employee { id = 7, Name = "zack", Age = 35, Gender = true, Salary = 8500 });
            List.Add(new Employee { id = 8, Name = "jack", Age = 33, Gender = true, Salary = 8000 });
            //Where
            UseWhere(List);
            //Count
            UseCount(List);
            //Any,至少有一条数据则返回True
            UseAny(List);
            //Single:只接收一条数据,0条或者多条直接语法上报错
            UseSingle(List);
            //SingleOrDefault:只接收一条数据,多条报错,0条返回默认值:null(因为Employee是引用类型,如果是int类型则返回默认值0);
            UseSingleOrDefault(List);

            //First:返回数据一条都没有语法上报错,有1条或更多返回第一条 类似Single
            //FirstOrDefault:类似SingleOrDefault

            //OrderBy:按照指定字段进行正序排序>>按照一个字段或者按照多个字段语法差异较大,需要注意
            UseOrderBy(List);
            //OrderByDescending:按照指定字段进行倒序排序

            //Skip(n)跳过第N条数据,Take(n)获取第N条数据
            UseSkipAndTake(List);

            //综合练习1:链式操作
            Console.WriteLine("This 链式操作");
            IEnumerable<Employee> items = List.Where(e => e.Age > 30).
                OrderBy(e => e.Age).Skip(1).Take(2);
            foreach (var item in items)
            {
                Console.WriteLine(item);
            }
            Console.WriteLine("--------");

            //Max:获取最大值
            UseMax(List);
            //Min、Average、Count、Sum 同Max类似

            //GroupBy():参数是分组条件表达式,返回值为IGrouping<Tkey,TSource>类型的泛型IEnumberable
            //也就是每一组以一个IGrouping对象的形式返回。IGrouping是一个继承自IEnumerable的接口
            //Key属性表示这一组的分组数据的值。例子:按年龄分组,获取每组人数、最高工资。可以用var简化编程
            UseGroupBy(List);

            //Select:投影操作>>把集合中的每一项转换成另外一种类型。Select与Groupby与匿名函数、max、min结合使用
            UseSelect(List);

            //集合转换:IEnumerable<T>转换成列表或数组
            IEnumerable<Employee> toListOrArray = List.Where(e => e.Salary > 6000);
            List<Employee> fromIEnumerableList = toListOrArray.ToList();
            Employee[] fromIEnumerableArray = toListOrArray.ToArray();

            //综合练习2:链式操作 需求:获取id>2的数据,然后按照Age分组,并且把分组按照Age排序,然后取前三条,最后再投影取得年龄、人数、平均工资
            var practice2 = List.Where(e => e.id > 2)
                .GroupBy(e => e.Age)
                .OrderBy(e => e.Key).Take(3)
                .Select(e => new 
                { 
                    Age = e.Key, 
                    CountPeople = e.Count(), 
                    AvgS = e.Average(e => e.Salary) 
                });
            foreach (var item in practice2)
                Console.WriteLine(item);

            
            //一种过时的语法:以上叫“Linq方法语法”,以下过时的语法称为查询语法>>类似SQL语法,最终编译结果与两种形式一致。
            var LikeSql = from e in List 
                          where e.Salary > 5000 
                          select new 
                          { 
                              e.Age,
                              e.Name,
                              Gender = e.Gender?"男":"女"
                          };
            foreach (var item in practice2)
                Console.WriteLine(item);

        }

         

        public static void UseWhere(List<Employee> List)
        {
            IEnumerable<Employee> items1 = List.Where(e => e.Age > 30);
            Console.WriteLine(items1);
            foreach (var item in items1)
                Console.WriteLine(item);
        }
        public static void UseCount(List<Employee> List)
        {
            Console.WriteLine(List.Count());
            Console.WriteLine(List.Count(e => e.Age > 20));
            Console.WriteLine(List.Count(e => e.Age > 20 && e.Salary > 8000));
        }
        public static void UseAny(List<Employee> List)
        {
            Console.WriteLine(List.Any());
            Console.WriteLine(List.Any(e => e.Salary > 300000));
            Console.WriteLine(List.Any(e => e.Salary < 8000));
        }
        public static void UseSingle(List<Employee> List)
        {
            //Employee e1 = List.Single(); 报错
            //Console.WriteLine(e1);
            Employee e2 = List.Where(e => e.Name == "jerry").Single();
            Console.WriteLine(e2);
            Employee e3 = List.Single(e => e.Name == "jack"); //Single可以传入委托,相比较于使用where语法更简洁
            Console.WriteLine(e3);
        }
        public static void UseSingleOrDefault(List<Employee> List)
        {
            //Employee e1 = List.Single(); 报错
            //Console.WriteLine(e1);
            Employee e3 = List.SingleOrDefault(e => e.Name == "jack");
            Console.WriteLine(e3);
            Employee e4 = List.SingleOrDefault(e => e.Name == "ssss");
            Console.WriteLine(e4); // 返回null;
            Console.WriteLine(e4==null); //验证是否是null
        }
        public static void UseOrderBy(List<Employee> List)
        {
            IEnumerable<Employee> items1 = List.OrderBy(e => e.Age); //根据年龄排序
            IEnumerable<Employee> items2 = List.OrderBy(e => e.Salary); //根据工资排序
            var items3 = List.OrderBy(e => e.Age).ThenByDescending(e => e.Salary); //优先按照年龄正序,次优先按照工资倒叙
            Console.WriteLine("This UseOrderBy");
            foreach (Employee item in items1)
                Console.WriteLine(item);
            Console.WriteLine("--------");
            foreach (Employee item in items2)
                Console.WriteLine(item);
            Console.WriteLine("--------");
            foreach (var item in items3)
                Console.WriteLine(item);
            Console.WriteLine("--------");
        }
        public static void UseSkipAndTake(List<Employee> list)
        {
            IEnumerable<Employee> items1 = list.Skip(2); //从第三条数据开始,跳过1.2条数据
            IEnumerable<Employee> items2 = list.Take(2); //从头开始获取2条数据
            IEnumerable<Employee> items3 = list.Skip(1).Take(3); //从第2条数据开始开始获取3条数据,跳过第一条数据
            Console.WriteLine("This UseSkipAndTake");
            foreach (Employee item in items1)
                Console.WriteLine(item);
            Console.WriteLine("--------");
            foreach (Employee item in items2)
                Console.WriteLine(item);
            Console.WriteLine("--------");
            foreach (Employee item in items3)
                Console.WriteLine(item);
            Console.WriteLine("--------");

        }
        public static void UseMax(List<Employee> list)
        {
            Console.WriteLine("This Max");

            int a = list.Max(a => a.Age); //年龄最大值 返回值是int类型
            int b = list.Where(a => a.id > 6).Max(a => a.Salary); //id大于6中工资最大值 返回值是int类型
            string name = list.Max(a => a.Name); //返回值是泛型,此时就是string类型,实现方式可以自行搜索:字符串比较大小算法
            Console.WriteLine($"年龄最大的是{a}");
            Console.WriteLine($"id大于6中工资最大是{b}");
            Console.WriteLine($"名字使用Max函数结果是:{name}");

            Console.WriteLine("--------");
        }
        public static void UseGroupBy(List<Employee> list)
        {
            Console.WriteLine("This UseGroupBy");

            //对应的sql:select age,max(Salary), from  t group by age;
            IEnumerable<IGrouping<int, Employee>> items = list.GroupBy(e => e.Age);
            foreach (IGrouping<int, Employee> item1 in items)
            {
                Console.WriteLine(item1.Key);
                Console.WriteLine($"最大工资{item1.Max(e=>e.Salary)}");
                foreach (Employee item2 in item1)
                {
                    Console.WriteLine(item2);
                }
            }

            Console.WriteLine("--------");
        }
        public static void UseSelect(List<Employee> list)
        {
            Console.WriteLine("This Select");
            IEnumerable<int> Ages = list.Select(e => e.Age); //只取出年龄信息
            foreach (var age in Ages)
            {
                Console.WriteLine(age);
            }
            IEnumerable<String> Names = list.Select(e => e.Name); //只取出名字信息
            foreach (var name in Names)
            {
                Console.WriteLine(name);
            }
            IEnumerable<String> NamesAndAges = list.Where(e=>e.Age>30).Select(e => e.Name+","+e.Age); //过滤后取出名字加年龄
            foreach (var item in NamesAndAges)
            {
                Console.WriteLine(item);
            }
            //Select与Groupby与匿名函数、max、min结合使用
            var items = list.GroupBy(e => e.Age).
                Select(e => new
                {
                    Age = e.Key,
                    MaxS = e.Max(e => e.Salary),
                    MinS = e.Min(e => e.Salary),
                    CountPeople = e.Count()
                }) ;
            foreach (var item in items)
                Console.WriteLine(item);

            Console.WriteLine("--------");
        }

    }
    class Employee
    {
        public long id { get; set; } //主键
        public string Name { get; set; } //名字
        public int Age { get; set; } //年龄
        public bool Gender { get; set; } //性别
        public int Salary { get; set; } //月薪
        public override string ToString()
        {
            return $"id={id},Name={Name},Age={Age},Gender={Gender},Salary={Salary}";
        }
    }

}

三、练习

P1:根据字符串求平均值

using System;
using System.Collections.Generic;
using System.Linq;
using ConsoleApp1;
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            //需求 :求str1的平均分
            string str1 = "53,33,55,888,9";
            string[] str2 = str1.Split(',');
            //方法一:
            int[] num1 = Array.ConvertAll(str2, e => int.Parse(e));
            double avgSorce1 = num1.Average(e => e);
            Console.WriteLine(avgSorce1);
            //方法二:用投影将string类型的数组转成int类型的IEnumerable
            IEnumerable<int> num2 = str2.Select(e => Convert.ToInt32(e));
            double avgSorce2 = num2.Average(e => e);
            Console.WriteLine(avgSorce2);
            //方法三:将方法二进行链式操作
            double avgSorce3 = str2.Select(e => Convert.ToInt32(e)).Average(e=>e);
            Console.WriteLine(avgSorce3);
        }

    }
}

P2:统计一个字符串中每个字母出现的频率(忽略大小写),然后按照从高到低的顺序输出出现频率高于2次的单词和其出现的频率;

using System;
using System.Collections.Generic;
using System.Linq;
using ConsoleApp1;
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            string str1 = "hello World,Hahah,heiheihei";
            var res = 
                str1.Where(e=>char.IsLetter(e)).
                Select(e => char.ToLower(e) ).
                GroupBy(e => e).
                Select(e => new { e.Key, count = e.Count() }).
                Where(e => e.count > 2).
                OrderByDescending(e=>e.count);
            foreach (var item in res)
            {
                Console.WriteLine(item);
            }
        }

    }
}