Linq教学

Linq教学

1 委托

1.1委托用法

委托是可以指向方法的类型,调用委托变量时执行的就是变量指向的方法

用法

delegate 返回类型 方法名(参数);

举例:

internal class Program
        {
            static void Main(string[] args)
            {
                /* string list = "12321312";
                var items = list.Where(c => char.IsLetter(c));*/
                int i = 5;
                Console.WriteLine(i);
                Console.WriteLine("-----------------");               
                D1 d1 = c1;             
                d1();             
                d1 = c2;                
                d1();
            }
            static void c1()
             {                
            	Console.WriteLine("这是c1方法");
             }

            static void c2()
            {                
            Console.WriteLine("这是c2方法");
            }

            delegate void D1();
}
1.2委托类型

.NET中定义了泛型委托Action(无返回值)和Func(有返回值),所以一般不用自定义委托类型。

用法:

Func=> Func<参数1类型,参数2类型,返回值类型> f = 方法

Action=> Action<参数1类型,参数2类型> a= 方法

举例:

internal class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("-----------------");  
                Func<int,int,int>f=Add;
                Func<int,int,string>f2=f33;
                Action<int,string> f6 =f8;

            }
            static int Add(int i,int j) {

               return i1+i2
            }
            static string f33(int i,int j)
            {
                return "xxx"  
            }

            static void f1()
            {

                Console.WriteLine("这是c2方法");
            }

    delegate void D1();
    }



}
1.3 委托方法

委托可以指定匿名方法

用法:

Func<int,int,string> f1=delegate (int i ,int b){

return $"{i}+{b}}"

}
string s =f1(1,2)
//第二种用法
Func<int,int,string> f2=(int i ,int b)=>{return $"{i}+{b}}"}
Console.Write(f2(1,3));

2 Linq 方法的背后

  • LINQ中提供了很多集合的拓展方法,配合lambda能简化数据处理。
  • 代码
int[]nums =new int []{3,99,88,77,7,8,9,66,15,7};
IEnumerableitems=nums.Where(i=>i>10);
//using System.Linq

上述问题如何通过方法实现

  • 实现方法:
internal class Program
{
static void Main(string[] args)
{
int[] nums = new int[] { 3, 99, 88, 77, 7, 8, 9, 66, 15, 7 };

var list = nums.Where(p => p > 10);


foreach (var item in list)
{
Console.WriteLine(item);
}
Console.WriteLine("-------where1---------");
var items2 = myWhere1(nums, a => a > 10);
foreach (var item in items2)
{
    Console.WriteLine(item);
}

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

var items3 = MyWhere(nums, a => a > 10);
foreach (var item in items3)
{
Console.WriteLine(item);
}
}
static IEnumerable myWhere1(IEnumerable nums, Func<int, bool> f)
{
List list = new List();
foreach (var item in nums)
{
if (f(item))
{
list.Add(item);
}
}
return list;
}
static IEnumerable MyWhere(IEnumerablenums, Func<int,bool> f)
{
foreach (var item in nums)
{
if (f(item) == true)
{
yield return item;
}



}

}
}

3 C#中var

var可以让编译器的“类型推断”来简化类型的声明,在LINQ中常用。

C#中的var和JavaScript的var不一样,仍然是强类型的。

C#中的弱类型是dynamic

4 linq中的拓展方法

LINQ中提供了大量类似Where的拓展方法,简化数据处理。大部分都在System.Linq命名空间中。

4.1 wh
  • 添加类
record 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; }
}
  • 添加基础数据
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 });
4.2Where

通过where进行筛选

IEnumerable list1 = list.Where(e => e.Salary > 2500 && e.Age < 35);

foreach (Employee e in list1)

{

Console.WriteLine(e);

}
4.3Count

可以计算满足条件的所有数量

int count1 = list.Count(e => e.Salary > 5000 || e.Age < 30);
int count2 = list.Where(e => e.Salary > 5000 || e.Age < 30).Count();
4.4 Any

只要有一条满足的情况下则为true

bool b1 = list.Any(e => e.Salary > 8000);
bool b2 = list.Where(e => e.Salary > 8000).Any();
4.5返回一条数据的方法
  • Single:有且只有一条满足条件的数据,超过一条或不存在则报错
  • SingleOrDefault:最多只有一条满足要求的数据,不存在则返回默认值,超过则报错
  • First:至少有一条,返回一条;不存在报错
  • FirstOrdefault:返回第一条或者默认值;不存在返回默认值
Employee e1 = list.Single(e => e.Id == 6);
Console.WriteLine(e1);
Employee? e2 = list.SingleOrDefault(e => e.Id == 9);
if (e2 == null)
{
    Console.WriteLine("没有Id==9的数据");
}
else
{
    Console.WriteLine(e2);
}
Employee e3 = list.First(e => e.Age > 30);
Console.WriteLine(e3);
Employee? e4 = list.FirstOrDefault(e => e.Age > 30);
if (e4 == null)
{
    Console.WriteLine("没有大于30岁的数据");
}
else
{
Console.WriteLine(e2);

}
Employee e5 = list.First(e => e.Salary > 9999);
4.6 Order排序
  • Order()对数据正序排序;

  • OrderByDescending()倒序排序;

  • list.OrderBy(e=>e.Age); 通过年龄排序

    对于简单类型排序,也许不用lambda表达式。

  • 特殊案例 按照最后一个字符排序;用Guid或者随机数进行排序。

Console.WriteLine("------按照年龄正序排列------");
var orderedItems1 = list.OrderBy(e => e.Age);
foreach (var item in orderedItems1)
{
    Console.WriteLine(item);
}
Console.WriteLine("------按照工资倒序排列------");
var orderedItems2 = list.OrderByDescending(e => e.Salary);
foreach (var item in orderedItems2)
{
Console.WriteLine(item);

}
-----------------------------
//通过GUid排序
var item2=list.orderBydescending(e=>Guid.NewGuid());
//随机数排序
var item3 =list.OrderByDescending(e=>rand.Next())
-------------------------
//多条件排序
//通过年龄进行排序,年龄相同的通过工资从打道夏排序
var items=list.OrderByDescending(e=>e.Age).thenBy(e=>e.Salary);
4.7 Skip,take 限制结果集,获取部分数据
  • skip(n) 跳过n条数据,Take(n)获取n条数据
  • 案例:获取从第二条开始获取3条数据
var orderedItems1 =list.Skip(2).Take(3);
// Skip(),Take()也可以单独使用
4.8 聚合函数
  • Max() 取最大

  • Min() 取最小

  • Average() 平均值

  • Sum() 求和

  • Count() 求数量

    LINQ中所有的拓展方法都是针对IEnumerable接口的,而几乎所有能返回集合的都返回IEnumerable,所以是可以吧几乎所有的方法“链式使用”的

//查询出年龄大于30的,工资最小的
list.Where(e=>e.Age>30).Min(e=>e.Salary)
4.9分组 GroupBy
  • GroupBy()方法参数是分组条件表达式,返回值为IGrouping<TKey,TSource>类型的泛型IEnumerable,也就是每一组以一个Grouping对象的形式返回,IGrouping 是一个继承自IEnumerable的接口,IGrouping中Key属性表示这一个分组数据的值。
  • 例子:根据年龄分组,获取每组人数,最高工资,平均工资。
IEnumerable> items = list.GroupBy(e => e.Age);

foreach (IGrouping item in items)

{

int age = item.Key;

int count = item.Count();

int maxSalary = item.Max(e => e.Salary);

double avgSalary = item.Average(e => e.Salary);

Console.WriteLine($"年龄{item.Key},人数{count},最高工资{maxSalary},平均工资{avgSalary}");

}
4.10 投影
  • 把集合中的每一项转换成另外的一种类型。
IEnumerable ages=list.Select(e=>e.Age);
  IEnumerable names=list.Select(e=>e.Gender?"男":"女");
  var dogs =list.Select(p=>new Dog{NickName=e.Name,Age=e.Age});
  • 投影与匿名函数相互
var list2= list.Select(e => new { Xingming = e.Name, Xingbie = e.Gender ? "男" : "女" });

foreach(var i in list2)

{

Console.WriteLine("姓名:" + i.Xingming + ",性别:" + i.Xingbie);

}
  • 练习
//通过年龄进行分组 求出这个年龄下的最高薪资和最低薪资以及这个年龄总共有多少人
var items1 =list.GroupBy(p=>p.Age).Select(p=> new {Nianling=p.Key,MaxS=p.Max(e=>e.Salary),MinS=p.Min(e=>e.Salary),Renshu=p.Count()});
 foreach(var e  in items1)
{
Console.WriteLine(e.Nianling+","+e.MaxS+","+e.MinS+","+e.Renshu);
}
4.11 集合的转换
  • 有一些地方需要数组类型或者List类型的变量,我们可以用ToArray()和ToList()分别把IEnumerable< T > 转换为数组类型和List< T >类型。

    • 操作
IEnumerable items2 = list.Where(p => p.Salary>6000);

  List list3 = items2.ToList();

  Employee[] array2 = items2.ToArray();
4.12 Linq查询语法
  • 上述使用 Where,OrderBy ,Select等拓展该方法进行数据查询的语法叫做“LINQ方法语法”

    ,还有一种“查询语法”的写法

    比如

var items3 = from e in list
  where e.Salary > 3000
  orderby e.Age
  select new
  {
  e.Name,
  e.Age,
  Gender = e.Gender ? "男":"女"
  };

5 面试中可能遇见的问题

  • 问题1 有一个用逗号分割的表示成绩的字符串如"61,90,100,99,18,22,38,66,80,93,55,50,89"计算这些成绩的平均值
string txt= "61,90,100,99,18,22,38,66,80,93,55,50,89";
//先通过,进行切割
var items = txt.Split(",");
//需要将其转换成 int 类型然后进行求平均值
double avg = items.Select(e=>Convert.ToInt32(e)).Average();
Console.WriteLine(avg);
  • 问题2 统计一个字符串中每个字母出现的频率(忽略大小写),然后按照从高到低的顺序输出频率高于2次的单词和其出现的的频率
//思路:首先先要去除空格和逗号,在将其转换成小写,再将其分组 获取次数 在进行排序
string s = "Hellow WORD,hhhhh,LaAALSDSADSs";
var items2 = s.Where(c => char.IsLetter(c)).Select(c => char.ToLower(c))
.GroupBy(c => c)
.Select(g => new { g.Key, Count = g.Count() })
.OrderByDescending(g => g.Count)
.Where(g=>g.Count>2);
foreach(var i in items2)
{
Console.WriteLine(i);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值