Linq知识
1. 基本语句:
From 临时变量 in 实现IEnumerable<T>接口的对象 where条件表达式
[order by条件] [group by条件] select 临时变量中被查询的值
Eg: int[] arr=new int[]{1,6,3,5,9,8,7,6};
Var m=from n in arr where n<5 order by ndescending select n;查询小于5并倒叙排列
2. 实现IEnumerable<T>接口的对象.linq方法名(lambda表达式)
Eg: string input = “hello world”;
Int count =input.Count(w=>w==’o’);//查询o出现的次数
//Linq里面如果委托的参数有两个,那就表示输入和输出,都是泛型
int[] a = newint[] { 1, 2, 6, 3, 4,9, 5 };
//1 linq查询
IEnumerable<int> linqQuery = from n in a where n < 5 select n;
foreach (int item in linqQuery)
{
Response.Write("<script>alert('" + item + "')</script>");
}
1.1 select查询
List<int> listInt = newList<int>();
listInt.Add(1);
listInt.Add(2);
listInt.Add(5);
listInt.Add(6);
IEnumerable<int> IenumInt =listInt.Select(m => m);
foreach (var item in IenumInt)
{
Response.Write("<script>alert('" + item + "')</script>");
}
//1.2 where查询简化
var arr = a.Where(w=> w < 5);
foreach (int n in arr)
{
Response.Write("<script>alert('" + n + "')</script>");
}
//2.count()包含数量查询
string Content = "I am XuBaiJin";
int s =Content.ToLower().Count(x => x == 'i');
Response.Write("<script>alert('" + s + "')</script>");
//3.orderBy()排序
List<string> listInt = newList<string>();
listInt.Add("我");
listInt.Add("我们是中国人");
listInt.Add("中国人");
listInt.Add("China是中国的英文");
listInt.Add("China");
listInt.Add("我属于中国");
listInt.Add("Maybe");
IEnumerable<string> stringArr =listInt.OrderBy(x => x.Length);
foreach (var item in stringArr)
{
Response.Write("<script>alert('" + item + "')</script>");
}
//延时标准操作符
//1.where 将符合条件的元素组织声称一个序列结果 原型有两个:
//public static IEnumerable<TSource>Where<TSource>(this IEnumerable<TSource> source, Func<TSource,bool> predicate);
//public static IEnumerable<TSource>Where<TSource>(this IEnumerable<TSource> source, Func<TSource,int, bool> predicate);
List<int> listInt = newList<int>();
listInt.Add(1);
listInt.Add(21);
listInt.Add(13);
listInt.Add(24);
listInt.Add(32);
listInt.Add(28);
//m值的是值,p指的是所有值的下标排列顺序,例如21的下表是1,24的下表是3
IEnumerable<int> IEInt =listInt.Where((m, p) => m > 20 && 4 > p && p > 0);
foreach (int item in IEInt)
{
Response.Write("<script>alert('" + item + "')</script>");
}
//2.select 根据输入序列中的元素创建相应的输出序列中的元素,输出序列元素可以与输入序列元素相同也可以不同
//public static IEnumerable<TResult>Select<TSource, TResult>(this IEnumerable<TSource> source,Func<TSource, int, TResult> selector);
//public static IEnumerable<TResult>Select<TSource, TResult>(this IEnumerable<TSource> source,Func<TSource, TResult> selector);
List<people> pList = newList<people>();
people p1 = newpeople(1, "张三", 21);
people p2 = newpeople(2, "李四", 23);
people p3 = newpeople(2, "王二", 21);
pList.Add(p1);
pList.Add(p2);
pList.Add(p3);
//直接查询名字
IEnumerable<string> pName =pList.Select(p => p.name);
foreach (string item in pName)
{
Response.Write("<script>alert('" + item + "')</script>");
}
//输出元素和下标返回一个新的匿名函数,因此要使用var而不能是IEnumberable<>
var newList =pList.Select((m, i) => new { index = i, m.name });
foreach (var item in newList)
{
//输出的是姓名和下标
Response.Write("<script>alert('" + item.name +","+item.index+ "')</script>");
}
publicclasspeople
{
publicint id { get; set; }
publicstring name { get; set; }
publicint age { get; set; }
public people(int id, string name, int age)
{
this.id = id;
this.name = name;
this.age = age;
}
}
//3.SelectMany根据输入序列的每一个元素,在输出序列中创建相应的零个或多个元素 与select不同 select只能根据输入序列创建一个对应的输出序列元素
//原型:
//public static IEnumerable<TResult>SelectMany<TSource, TResult>(this IEnumerable<TSource>source,Func<TSource, IEnumerable<TResult>> selector);
//public static IEnumerable<TResult>SelectMany<TSource, TResult>(this IEnumerable<TSource> source,Func<TSource, int, IEnumerable<TResult>> selector);
//public static IEnumerable<TResult>SelectMany<TSource, TCollection, TResult>(this IEnumerable<TSource>source, Func<TSource, IEnumerable<TCollection>> collectionSelector,Func<TSource, TCollection, TResult> resultSelector);
//public static IEnumerable<TResult>SelectMany<TSource, TCollection, TResult>(this IEnumerable<TSource>source, Func<TSource, int, IEnumerable<TCollection>>collectionSelector, Func<TSource, TCollection, TResult> resultSelector);
List<People> pList = newList<People>();
People p1 = newPeople(1, "张飞", 21);
People p2 = newPeople(1, "关羽", 22);
People p3 = newPeople(1, "刘备", 23);
pList.Add(p1);
pList.Add(p2);
pList.Add(p3);
var newList =pList.SelectMany(p => p.name);
//newList是一个包含所有p.name的字符的集合IEnumerable<char>
//返回的是字符“张”“飞”“关”“羽”“刘”“备”,而select返回的则是“张飞”“关羽”“刘备”
foreach (var item in newList)
{
Response.Write("<script>alert('" + item + "')</script>");
}
var items =pList.SelectMany((p, i) => i < 2 ? p.name.ToArray() : newchar[] { });
//返回的是字符“张”“飞”“关”“羽”
foreach (var item in items)
{
Response.Write("<script>alert('" + item + "')</script>");
}
publicclassPeople
{
publicint id { get; set; }
publicstring name { get; set; }
publicint age { get; set; }
public People(int id, string name, int age)
{
this.id = id;
this.name = name;
this.age = age;
}
}
//Select()每一次遍历,输出的是T,然后将所有遍历后得到的T组合成一个IEnumerable< T >。
//SelectMany()每遍历一次,输出的是IEnumerable < T >,然后合并成一个大的IEnumerable< T >。一般用于嵌套的集合中
List<List<int>> numbers = newList<List<int>>()
{
newList<int>{1,2,3},
newList<int>{4,5,6},
newList<int>{7,8,9}
};
IEnumerable<int> result =numbers.SelectMany(collection => collection); //collection的类型是List<int>,要求返回IEnumerable<int>
foreach (int i in result)
{
Response.Write("<script>alert('" + i + "')</script>");
}
//4.Take Take操作符用于从输入序列中返回指定数量的元素,常用于分页。
// public static IEnumerable<TSource>Take<TSource>(this IEnumerable<TSource> source, int count);
List<People> pList = newList<People>();
People p1 = newPeople(1, "张飞", 21);
People p2 = newPeople(1, "关羽", 22);
People p3 = newPeople(1, "刘备", 23);
pList.Add(p1);
pList.Add(p2);
pList.Add(p3);
//take只接受一个整数,返回的结果是数量 取出前几条(take里面的数字决定)
IEnumerable<People> newList =pList.Take(2);
//只取"张飞"“关羽”
foreach (var item in newList)
{
Response.Write("<script>alert('" + item.name + "')</script>"); //返回 张飞 关羽
}
//TakeWhile操作符用于从输入序列中返回指定数量且满足一定条件的元素
//如果出现一个不符合条件的就终止,哪怕后面有符合条件的也不要
//原型:
//public static IEnumerable<TSource>TakeWhile<TSource>(this IEnumerable<TSource> source,Func<TSource, bool> predicate);
//public static IEnumerable<TSource>TakeWhile<TSource>(this IEnumerable<TSource> source, Func<TSource,int, bool> predicate);
List<People> pList = newList<People>();
People p1 = newPeople(1, "张飞", 21);
People p2 = newPeople(1, "关羽", 22);
People p3 = newPeople(1, "刘备", 23);
People p4 = newPeople(1, "孔明", 21);
pList.Add(p1);
pList.Add(p2);
pList.Add(p3);
pList.Add(p4);
//年龄小于23的,刘备>23所以在此终止,因此只有“张飞”“关羽”符合条件
IEnumerable<People> newList =pList.TakeWhile(p => p.age<23);
foreach (var item in newList)
{
Response.Write("<script>alert('" + item.name+"')</script>");
}
//年龄小于23的,刘备>23所以在此终止,下标<1的因此只有“张飞”
IEnumerable<People> newLists = pList.TakeWhile((p,i) => p.age < 23 && i < 1);
foreach (var item in newLists)
{
Response.Write("<script>alert('" + item.name + "')</script>");
}
//Skip 从输入序列中跳过指定数量的元素,返回由序列中剩余的元素所组成的新序列
//public static IEnumerable<TSource>Skip<TSource>(this IEnumerable<TSource> source, int count);
List<People> pList = newList<People>();
People p1 = newPeople(1, "张飞", 21);
People p2 = newPeople(1, "关羽", 22);
People p3 = newPeople(1, "刘备", 23);
People p4 = newPeople(1, "孔明", 21);
pList.Add(p1);
pList.Add(p2);
pList.Add(p3);
pList.Add(p4);
//跳过skip后面的数的个数
IEnumerable<People> newList =pList.Skip(2);
//输出“刘备”“孔明”
foreach (People item in newList)
{
Response.Write("<script>alert('" + item.name + "')</script>");
}
//SkipWhile 用于从输入序列中跳过满足一定条件指定数量的元素
//public static IEnumerable<TSource>SkipWhile<TSource>(this IEnumerable<TSource> source,Func<TSource, bool> predicate);
//public static IEnumerable<TSource>SkipWhile<TSource>(this IEnumerable<TSource> source,Func<TSource, int, bool> predicate);
List<People> pList = newList<People>();
People p1 = newPeople(1, "张飞", 21);
People p2 = newPeople(2, "关羽", 22);
People p3 = newPeople(3, "刘备", 23);
People p4 = newPeople(4, "孔明", 21);
pList.Add(p1);
pList.Add(p2);
pList.Add(p3);
pList.Add(p4);
IEnumerable<People> newList =pList.SkipWhile(p => p.age < 23);
//年龄<23到“刘备”开始输出,因此输出“刘备”“孔明”
foreach (People item in newList)
{
Response.Write("<script>alert('" + item.name + "')</script>");
}
//年龄小于23的有张飞关羽,但是下标小于1的只有张飞,因此输出“关羽”“刘备”“孔明”
IEnumerable<People> newLists =pList.SkipWhile((p, i) => p.age < 23 && i < 1);
foreach (People item in newLists)
{
Response.Write("<script>alert('" + item.name + "')</script>");
}
//OrderBy 顺序 OrderByDescending 逆序 ThenBy在orderBy或orderByDescending之后按照另一种特定序列进行排序 ThenByDescending与ThenBy相反
//Reverse生成一个与输入序列中元素相同,但是元素排列顺序相反的新序列
List<People> pList = newList<People>();
People p1 = newPeople(1, "张飞", 21);
People p2 = newPeople(2, "关羽", 22);
People p3 = newPeople(3, "刘备", 23);
People p4 = newPeople(4, "孔明", 21);
pList.Add(p1);
pList.Add(p2);
pList.Add(p3);
pList.Add(p4);
IEnumerable<People> newList =pList.Reverse<People>(); //此处用的是List<T>,必须要写类型参数,因为List<T>本身也有个同名方法
foreach (People item in newList)
{
Response.Write("<script>alert('" + item.name + "')</script>");
}
//Concat连接两个序列,生成一个新的序列
//IEnumerable<People> newList =pList.Concat(pList1);
Join 类似于SQL语句中的Join语句用于连接多个表,Linq to OBJECT中Join操作符可以用来连接两个输入序列。
var Items = pList.Join(rList, p => p.Id, r => r.PId, (p, r) => new { Name = p.Name, WarRecord = r.WarRecord });
GroupJoin 用于连接两个输入序列,但与Join操作符不同稍有不同
varItems1 = pList.GroupJoin(rList, p => p.Id, r => r.PId, (p, List1) => new{ Name = p.Name, WarRecords = List1.Sum(r=>r.WarRecord) });
GroupBy 类似于SQL语言仲的Gruop By语句,这里的GroupBy操作符用于将输入序列中的元素进行分组。
var pList1 = pList.GroupBy(p=>p.Age);
Distinct 类似于SQL语句中的Distinct语句,这里的Distinct操作符也用于去除一个序列中的重复元素。
IEnumerable<int> IEInt = listInt.Distinct();
Union 用于将两个序列中的元素合并成一个新的序列,新序列将自动去除重复的元素。
IEnumerable<int> IEInt1 = listInt.Union(listInt1);
Intersect 会将两个输入序列中的重复元素,即同时存在于两个序列中的元素挑选出来,生成一个新的集合,也就是求交集。
IEnumerable<int> IEInt = listInt.Intersect(listInt1);
Except 可以实现一种集合之间的减法运算,它返回两个序列中存在于第一个序列但不存在于第二个序列的元素所组成的新序列。
IEnumerable<int> IEInt = listInt.Except(listInt1);
Cast 非泛型转换为泛型
ArrayList al = new ArrayList();
al.Add(1);
al.Add(2);
al.Add(3);
IEnumerable<int> IEInt = al.Cast<int>(); //非泛型转泛型
foreach (var i in IEInt)
{
Console.WriteLine(i); //输出 1 2 3
}
Console.ReadKey();
OfType OfType与Cast类似,不同的是cast转换失败会抛出异常,ofType仅会将能够转换成功的进行转换,并将结果添加到结果序列中,ofType更加安全
ArrayList al = new ArrayList();
al.Add(1);
al.Add(2);
al.Add("a");
//IEnumerable<int> IECast = al.Cast<int>(); //抛出异常
//foreach (var i in IECast)
//{
// Console.WriteLine(i);
//}
IEnumerable<int> IEOfType = al.OfType<int>();
foreach (int i in IEOfType)
{
Console.WriteLine(i); //输出 1 2 其中转换不了的a不转换
}
Console.ReadKey();
DefaultEmpty 用来为一个空的输入序列生成一个对应的含有默认元素的新序列。引用类型为null,值类型为相应的默认值。有些标准操作符在一个空的序列上调用时会抛出一个异常,而DefaultEmpty恰恰可以解决这个问题。
List<string> ListInt = new List<string>();
ListInt.Add("one");
ListInt.Add("two");
ListInt.Add("three");
string str = ListInt.Where(s => s.StartsWith("a")).DefaultIfEmpty().First();
Console.WriteLine(str); //什么也不输出,或者说输出空白
//string str1 = ListInt.Where(s => s.StartsWith("a")).First(); //如果去掉DefaultEmpty就会报异常("序列中不包含任何元素")
Console.ReadKey();
Range操作符用于辅助生成一个整数序列。
IEnumerable<int> ints = Enumerable.Range(1,10);
foreach (int i in ints)
{
Console.WriteLine(i); //输出 1 2 3 4 5 6 7 8 9 10
}
Console.ReadKey();
Repeat操作符用于生成一个包含指定数量重复元素的序列。
IEnumerable<int> ints = Enumerable.Repeat(1,10);
foreach (int i in ints)
{
Console.WriteLine(i); //输出 1 1 1 1 1 1 1 1 1 1
}
Empty操作符用于生成一个包含指定类型元素的空序列。
IEnumerable<int> ints = Enumerable.Empty<int>();
Console.WriteLine(ints.Count()); //输出0