Linq
作者:互联网
一、常用函数
- Where:每一项数据都会经过predicate(传入的委托lambda表达式)的测试,如果对元素执行predicate后返回值为True,则这个元素会添加到结果数组中
- Count:每一项数据都会经过predicate(传入的委托lambda表达式)的测试,如果对元素执行predicate后返回值为True,则返回结果加1
注:假如Count不带任何参数,返回的是集合的元素个数
- Any:返回布尔类型,集合中是否有至少一条执行predicate后返回值为True的元素
如果Any不带任何参数,返回的是数组是否至少有一条数据
- Order:升序排序
- 单字段排序
- 多字段排序:先按年龄升序,假如年龄一样,则按工资升序
- 多字段排序:先按年龄升序,假如年龄一样,则按工资降序
注:这种多字段排序不能写两个OrderBy如下,否则它只会用最后一个OrderBy
IEnumerable<Employee> item5 = list.OrderBy(i => i.Age ).OrderBy(i => i.Salary);
- 单字段排序
- OrderByDescending:倒序排序
- OrderBy高级用法:OrderBy要不就按升序,要不就按降序。以下方法可以按指定顺序排列。
- 类准备:
Public Class FeederGetPointXYA
Public Index As Integer
Public Index1 As Integer
Public X As Double
Public Y As Double
Public A As Double
Public mStatue As huanghaiSmallRowStatue
Sub New(mIndex As Integer, mIndex1 As Integer, ms As huanghaiSmallRowStatue)
Index = mIndex
Index1 = mIndex1
mStatue = ms
End Sub
End Class
- 实现
ListAA.Add(New FeederGetPointXYA(1, 8, huanghaiSmallRowStatue.已抛料))
ListAA.Add(New FeederGetPointXYA(2, 7, huanghaiSmallRowStatue.已抛料))
ListAA.Add(New FeederGetPointXYA(3, 6, huanghaiSmallRowStatue.拍照贴合点OK))
ListAA.Add(New FeederGetPointXYA(4, 5, huanghaiSmallRowStatue.拍照贴合点OK))
ListAA.Add(New FeederGetPointXYA(5, 4, huanghaiSmallRowStatue.Null))
ListAA.Add(New FeederGetPointXYA(6, 3, huanghaiSmallRowStatue.Null))
ListAA.Add(New FeederGetPointXYA(7, 2, huanghaiSmallRowStatue.材料已拍照OK))
ListAA.Add(New FeederGetPointXYA(8, 1, huanghaiSmallRowStatue.Null))
'自定义排序规则
Dim SortRule() As huanghaiSmallRowStatue = {huanghaiSmallRowStatue.已抛料, huanghaiSmallRowStatue.Null, huanghaiSmallRowStatue.拍照贴合点OK}
Dim ListOrder As List(Of huanghaiSmallRowStatue) = SortRule.ToList()
Dim list00 = ListAA.OrderBy(Function(mmFeeder As FeederGetPointXYA) As Integer
Dim mIndex As Integer = ListOrder.IndexOf(mmFeeder.mStatue)
If mIndex <> -1 Then
Return mIndex
Else
Return ListAA.Count - 1 '加这个的好处是SortRule没添加规则时,排在最后(即上述的"材料已拍照OK"类型会排在最后 )
End If
End Function).
ThenByDescending(Function(mmFeeder As FeederGetPointXYA) As Integer '二次排序
Return mmFeeder.Index
End Function).ToList
- 结果:
(2, 7, huanghaiSmallRowStatue.已抛料)
(1, 8, huanghaiSmallRowStatue.已抛料)
(8, 1, huanghaiSmallRowStatue.Null)
(6, 3, huanghaiSmallRowStatue.Null)
(5, 4, huanghaiSmallRowStatue.Null)
(4, 5, huanghaiSmallRowStatue.拍照贴合点OK)
(3, 6, huanghaiSmallRowStatue.拍照贴合点OK)
(7, 2, huanghaiSmallRowStatue.材料已拍照OK)
- 限制结果集,获取集合中的某一部分数据
- 原数据
- 跳过3条,取两条
二、防御性函数
- Single:有且只有一条数据满足要求。假如有多条或者没有则会报错
- 多于一条数据,所以报错
- 0条数据也会报错
- 有且仅有一个,输出唯一一个
- 多于一条数据,所以报错
- SingleOrDefaule:最多只有一条满足要求。假如有多条则会报错,假如0条或一条,则返回默认值(自定义类会返回Nothing或Null,Integer类型返回0)
- 假如一个都没有,返回默认值
- 假若只有一个,则返回一个
- First:至少有一条数据,返回第一条。假如一条都没有则会报错。
- 一条都没有,报错
- 多条,返回第一条
- FirstOrDefault:至少有一条数据,返回第一条,假如都没有则返回默认值
- 一条都没有返回默认值
- 以上四种是防御性变成,宁愿报错也不让数据继续错误下去。
三、聚合函数
1、Max/Min/Average/Sum
返回的是不是List的对象,而是double最大值
2、链式调用Linq时,假如链中间出现一个空值处理方法:在可能结果集合为空的linq后加.DefaultIfEmpty(***)给一个默认值
如下:链式调用Linq求Where筛选后的最大值,但是调用Where后,结果为空。没有符合要求的。再往后的Select
就会报错。
解决办法:
Vb.net 调用方式:
四、分组函数
分组:GroupBy,按传入表达式分组,相同的则分为同一组
也可以用var让编译器自动判断类型。
2、巧用分组函数,实现判断linq数组是否有重复
Vb.net 调用方式:
四、投影函数
投影:Select(跟SQL数据库中的语句一样)把集合中的的每一项按照某种规则转换生成另外的一个集合
- 按年龄生成一个新的数组(因为年龄是整数,所以它会生产一个整形数组),顺序跟原数组顺序
- 也可以多字段
- 对集合的所有元素工资减少5000
- 也可以映射另一个类的对象
- 上述映射到另一个类上,一定要新建一个Dog类,但是程序中往往只是需要中间结果处理一下,可以用匿名类来代替Dog类。省去新定义类的麻烦
- 匿名类用到var类型推断,如下
- 所以可以通过匿名类来实现以上功能
var item11 = list.Select(e => new { Name= e.Name, Age= e.Age });
- 匿名类用到var类型推断,如下
五、Take
- Take从序列的开头返回指定数量的连续元素
ListAA.Add(New FeederGetPointXYA(1, 6, huanghaiSmallRowStatue.已抛料))
ListAA.Add(New FeederGetPointXYA(2, 5, huanghaiSmallRowStatue.已抛料))
ListAA.Add(New FeederGetPointXYA(3, 4, huanghaiSmallRowStatue.拍照贴合点OK))
ListAA.Add(New FeederGetPointXYA(4, 3, huanghaiSmallRowStatue.拍照贴合点OK))
ListAA.Add(New FeederGetPointXYA(5, 2, huanghaiSmallRowStatue.Null))
ListAA.Add(New FeederGetPointXYA(1, 8, huanghaiSmallRowStatue.已贴合))
ListAA.Add(New FeederGetPointXYA(2, 9, huanghaiSmallRowStatue.已贴合))
'从序列的开头返回指定数量的连续元素
Dim ListBB = ListAA.Take(3).ToList() '取出数组的前三个元素
- TakeWhile是从头开始判断,遇到不满足条件的就中止,无论后续是否还有符合条件的元素
- TakeWhile与Where不同,Where是获取符合条件的所有元素
'结果也是取出数组的前三个元素,尽管后面mmFeeder.Index有符合的也不返回了
Dim ListDD = ListAA.TakeWhile(Function(mmFeeder As FeederGetPointXYA) As Boolean
If mmFeeder.Index < 4 Then
Return True
Else
Return False
End If
End Function).ToList
- TakeWhile还可以按数组序号取出
'取出前三个元素
Dim ListCC = ListAA.TakeWhile(Function(mmFeeder As FeederGetPointXYA, mIdx As Integer) As Boolean
If mIdx < 3 Then
Return True
Else
Return False
End If
End Function).ToList
五、数组删除元素
通过遍历把数组中元素删除时,由于每删除一次,数组个数会发生改变。从而导致for循环报错 集合已修改,如下
解决办法:在遍历的数组后面加 .ToArray()
六、综合例子
链式调用:var item12 = list.Where(e => e.Id > 2).GroupBy(e => e.Age).OrderBy(g=>g.Key).Take(3).
Select(h=> new { NL=h.Key ,RS=h.Count() ,PJ=h.Average(k=>k.Salary)}) ;
list.Where(e => e.Id > 2) (取出ID大于2的元素,其中e的类型是Employee)
.GroupBy(e => e.Age) (继续按年龄分组,年龄一样的分为一组存放到Key中,其中e的类型是IGrouping<int,Employee>)
.OrderBy(g=>g.Key) (组合继续按年龄排序,其中g的类型是IGrouping<int,Employee>)
.Take(3) (取出前面3组)
. Select(h=> new { NL=h.Key ,RS=h.Count() ,PJ=h.Average(k=>k.Salary)})
(对于结果的三组中的没一组进行映射,其中h类型是IGrouping<int,Employee>,k类型是Employee)
全部代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Linq
{
class Program
{
static void Main(string[] args)
{
List<Employee> list = new List<Employee>();
list.Add(new Employee { Id = 1, Name = "hh1", Age = 28, Gender = true, Salary = 5000 });
list.Add(new Employee { Id = 2, Name = "hh2", Age = 33, Gender = true, Salary = 3000 });
list.Add(new Employee { Id = 3, Name = "hh3", Age = 35, Gender = false, Salary = 9000 });
list.Add(new Employee { Id = 4, Name = "hh4", Age = 16, Gender = false, Salary =2000 });
list.Add(new Employee { Id = 5, Name = "hh5", Age = 25, Gender = true, Salary =1000 });
list.Add(new Employee { Id = 6, Name = "hh6", Age = 35, Gender = false, Salary = 8000 });
list.Add(new Employee { Id = 7, Name = "hh7", Age = 35, Gender = false, Salary = 8500 });
list.Add(new Employee { Id = 8, Name = "hh8", Age = 33, Gender = true, Salary = 8000 });
var item12 = list.Where(e => e.Id > 2).GroupBy(e => e.Age).OrderBy(g=>g.Key).Take(3).
Select(h=> new { NL=h.Key ,RS=h.Count() ,PJ=h.Average(k=>k.Salary)}) ;
foreach (var i in item12)
{
Console.WriteLine(i.NL + "," + i.RS + "," + i.PJ);
};
//foreach (var g in item12)
// {
// Console.WriteLine(g.Key);
// foreach (Employee e in g)
// {
// Console.WriteLine(e);
// }
// Console.WriteLine("*******************");
// }
Console.ReadKey();
//foreach (string e1 in item12)
//{
// Console.WriteLine(e1);
//};
//var item11 = list.Select(e => new { Name= e.Name, Age= e.Age });
//var item10 = new { Name = "eee", Age = 20 };
//Console.WriteLine(item10.Name);
//Console.WriteLine(item10.Age);
//Console.ReadKey();
//IEnumerable<Employee> item9 =
// list.Select( e=>new Employee { Id = e.Id, Name = e.Name, Age = e.Age, Gender = e.Gender, Salary = e.Salary - 5000 });
//IEnumerable<Dog> item8 = list.Select(e => new Dog(e.Name, e.Age));
//IEnumerable<string> item8 = list.Select(e => e.Age + "," + e.Salary);
//foreach (string e1 in item8)
//{
// Console.WriteLine(e1);
//};
//Console.ReadKey();
//var item5 = list.GroupBy(e => e.Age);
//foreach (var g in item5)
//{
// Console.WriteLine(g.Key);
// foreach (Employee e in g)
// {
// Console.WriteLine(e);
// }
// Console.WriteLine("*******************");
//}
//double K = list.Max(e => e.Salary);
//Console.WriteLine(K);
//Console.ReadKey();
//IEnumerable<Employee> item5 = list.OrderBy(i => i.Age ).OrderBy(i => i.Salary);
//IEnumerable<Employee> item6 = item5.Skip(3).Take(2);
//foreach (Employee e in item6)
//{
// Console.WriteLine(e);
//}
//Console.ReadKey();
//Employee el6 = list.FirstOrDefault(e => e.Salary > 10000);
//Console.WriteLine(el6);
//Console.ReadKey();
//Employee el5 = list.First(e => e.Salary >1);
//Console.WriteLine(el5);
//Console.ReadKey();
Employee el4 = list.SingleOrDefault(e => e.Name == "123");
Console.WriteLine(el4);
Console.ReadKey();
//Employee el1= list.Single();
//Employee el2 = list.Single(e=>e.Name== "123");
Employee el3 = list.Single(e => e.Name == "hh8");
Console.WriteLine(el3);
Console.ReadKey();
//Any---至少有一条数据,是否至少有一条工资大于100000的
bool RetBln = list.Any(e => e.Salary > 100000);
Console.WriteLine(RetBln);
Console.ReadKey();
//Count---筛选年龄大于30且工资大于8000的集合的个数
int RetCount = list.Count(e => e.Age > 30 && e.Salary > 8000);
Console.WriteLine(RetCount);
Console.ReadKey();
//Where---筛选年龄大于30的集合
IEnumerable<Employee> item1= list.Where(i => i.Age > 30);
foreach (Employee e in item1)
{
Console.WriteLine(e);
}
}
}
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}";
}
}
class Dog
{
public string Name { get; set; }
public int Age { get; set; }
public Dog(string nName,int mAge)
{
Name = nName;
Age = mAge;
}
}
}
标签:Salary,Console,Name,huanghaiSmallRowStatue,Age,list,Linq 来源: https://www.cnblogs.com/ihh2021/p/16611678.html