C# LINQ 基础和常用的扩展方法

发布时间 2023-11-26 18:23:10作者: Simian_2018_12_22

1. 自定义Where方法

static void MM(string[] args)
{
    IEnumerable<int> ints = new int[] { 1, 2, 4, 63, 12, 34, 46, 12, 45, 12456 };
    // 使用LINQ中的Where方法
    //IEnumerable<int> ints2 = ints.Where(a => a > 10);
    // 使用自定义的Where方法
    IEnumerable<int> ints2 = MyWhere(ints, a => a > 10);
    foreach (int i in ints2)
    {
        Console.WriteLine(i);
    }
}
// 自定义的Where方法
static IEnumerable<int> MyWhere(IEnumerable<int> ints,Func<int,bool> f)
{
    List<int> list = new List<int>();
    foreach (int i in ints)
    {
        if (f(i))
        {
            yield return i;
        }
    }
}

2. 常用的方法

2.1 初始化数据集合
List<Employee> employees = new List<Employee>();
list.Add(new Employee(){Id = 1,Name = "张三",Age = 16,Gender = false,Salary = 2000});
list.Add(new Employee(){Id = 2,Name = "凌洋",Age = 32,Gender = false,Salary = 1500});
list.Add(new Employee(){Id = 3,Name = "夏一桐",Age = 11,Gender = true,Salary = 4000});
list.Add(new Employee(){Id = 4,Name = "崔今生",Age = 32,Gender = false,Salary = 2000});
list.Add(new Employee(){Id = 5,Name = "孙河",Age = 23,Gender = true,Salary = 5000});
list.Add(new Employee(){Id = 6,Name = "方晴",Age = 26,Gender = true,Salary = 8000});
list.Add(new Employee(){Id = 7,Name = "赵七",Age = 32,Gender = true,Salary = 3000});
list.Add(new Employee(){Id = 8,Name = "包卫丽",Age = 26 ,Gender = true,Salary = 4500});
2.2 Where

Where 获取满足条件的数据 返回值:IEnumerable<>集合

IEnumerable<Employee> employees1 = employees.Where(a => a.Salary > 3000 && a.Age > 30);
foreach (Employee employee in employees1)
{
    Console.WriteLine(employee.ToString());
}
2.3 Any

Any 判断集合中是否最少有一条满足他条件的数据 返回值:bool

Console.WriteLine(employees.Any(a => a.Id > 100));
Console.WriteLine(employees.Any(a => a.Id > 7));
2.4 Count

Count 获取集合中满足条件的数量 返回值:int

Console.WriteLine(employees.Count(a => a.Id > 100));
Console.WriteLine(employees.Count(a => a.Id > 7));
2.5 Single

Single 有并且只有一条满足条件的数据,有多条满足条件的数据提示错误,未找到满足条件的数据也会提示错误

//Employee employee1 = employees.Single(a=>a.Id>1); //报错
//Employee employee1 = employees.Single(a => a.Id == 11); //报错
Employee employee1 = employees.Single(a => a.Id == 1); // 正常
Console.WriteLine(employee1);
2.6 SingleOrDefault

SingleOrDefault 最多只有一条满足条件的数据,未找到满足条件的数据返回该数据类型的默认值

//Employee employee2 = employees.SingleOrDefault(a => a.Id > 1); //报错
//Employee employee2 = employees.SingleOrDefault(a => a.Id == 11); //正常
Employee employee2 = employees.SingleOrDefault(a => a.Id == 1); // 正常
Console.WriteLine(employee2);
2.7 First

First 最少有一条满足条件的数据,有多条满足条件的数据返回第一条,未找到满足条件的数据提示错误

//Employee employee3 = employees.First(a => a.Id > 2); // 正常
//Employee employee3 = employees.First(a => a.Id == 22); // 报错
Employee employee3 = employees.First(a => a.Id == 2); // 正常
Console.WriteLine(employee3);
2.8 FirstOrDefault

Where 获取满足条件的数据 返回值:IEnumerable<>集合

//Employee employee4 = employees.FirstOrDefault(a => a.Id > 2); // 正常
//Employee employee4 = employees.FirstOrDefault(a => a.Id == 22); // 正常
Employee employee4 = employees.FirstOrDefault(a => a.Id == 2); // 正常
Console.WriteLine(employee4);
2.9 OrderBy

OrderBy 正序排序

IEnumerable<Employee> employees2 = employees.OrderBy(a => a.Salary);
foreach (Employee employee in employees2)
{
    Console.WriteLine(employee);
}
2.10 OrderByDescending

OrderByDescending 倒序排序

IEnumerable<Employee> employees3 = employees.OrderByDescending(a => a.Salary);
foreach (Employee employee in employees3)
{
    Console.WriteLine(employee);
}
2.11 OrderBy().ThenBy

OrderBy().ThenBy 排序完后再进行小范围的排序

IEnumerable<Employee> employees4 = employees.OrderBy(a => a.Gender).ThenByDescending(a=>a.Salary).ThenBy(a=>a.Age);
foreach (Employee employee in employees4)
{
    Console.WriteLine(employee);
}
2.12 Skip

Skip 跳过多少条数据

IEnumerable<Employee> employees5 = employees.Where(a=>a.Gender==false).OrderBy(a=>a.Salary).Skip(1);
foreach (Employee employee in employees5)
{
    Console.WriteLine(employee);
}
2.13 Take

Take 取几条数据

IEnumerable<Employee> employees6 = employees.Where(a => a.Gender == false).OrderBy(a => a.Salary).Take(1);
foreach (Employee employee in employees6)
{
    Console.WriteLine(employee);
}
2.14 SKip+Take

SKip+Take 跳过几条取几条

IEnumerable<Employee> employees7 = employees.Where(a => a.Gender == false).OrderBy(a => a.Salary).Skip(1).Take(2);
foreach (Employee employee in employees7)
{
    Console.WriteLine(employee);
}
2.15 GroupBy + Max + Min + Average

GroupBy(g=>g) 分组,返回值是IEnumerable<IGrouping<g的类型, g的类型>>类型
Max(g=>g) 获取最大值 返回值是g的类型
Min(g=>g) 获取最小值 返回值是g的类型
Average(g=>g) 获取平均值 返回值是g的类型

IEnumerable<IGrouping<int, Employee>> employees1 = employees.OrderBy(e=>e.Age).GroupBy(e => e.Age);
foreach (IGrouping<int,Employee> g in employees1)
{
    Console.WriteLine(g.Key);
    Console.WriteLine("分组中的最大工资:"+g.Max(e=>e.Salary));
    Console.WriteLine("分组中的最小工资:" + g.Min(e=>e.Salary));
    Console.WriteLine("分组中的平均工资:" + g.Average(e=>e.Salary));
    Console.WriteLine("分组中数量:" + g.Count());
    foreach (Employee e in g)
    {
        Console.WriteLine(e);
    }
}
2.16 Select(映射)

Select 映射一种新的类型

var ls = employees.Select(a => new { XM = a.Name, NL = a.Age, XB = a.Gender ? "男" : "女" });
foreach (var e in ls)
{
    Console.WriteLine(e);
}

案例:根据年龄进行分组,获取每组中年龄、最大工资、最小工资、平均工资、和分组个数

var ls1 = employees.GroupBy(a => a.Age).Select(a => new { 
    Age = a.Key,
    MaxS = a.Max(g => g.Salary),
    MinS = a.Min(g=>g.Salary),
    AvgS = a.Average(g => g.Salary),
    Count = a.Count()
});
foreach (var e in ls1)
{
    Console.WriteLine(e);
}
3 实际应用题

获取字符串中成绩的平均值

string s = "61,90,100,99,18,22,38,66,80,93,55,50,89";
IEnumerable<string> l = s.Split(",");
Console.WriteLine(l.Average(a=>Convert.ToDouble(a)));

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

string s = "KhKlkKHhfadsf  1111  JHLFDSdaskfjlLKHDSA";
var chars = s.Where(c=>char.IsLetter(c)).Select(c=>char.ToLower(c)).GroupBy(x => x).OrderByDescending(g=>g.Count()).Where(g=>g.Count() > 2).Select(c=>new { dc = c.Key,pl = c.Count()});
foreach (var c in chars)
{
    Console.WriteLine(c);
}