LINQ、SQO
LINQ
语言集成查询(Language Integrated Query,LINQ)。
LINQ语句,子句from、select、where、orderby、descending等都是预定义的关键字。查询表达式必须以from开头,以select或group子句结尾,在这两个子句之间,可以使用where、orderby、join、let和其他from子句。
SQO
标准查询运算符SQO(Standard Query Operator),定义在System.Linq.Enumerable类中的50多个为IEnumerable<T>准备的扩展方法,这些方法用来对操作的集合进行查询筛选等操作。
编译器会转换LINQ查询,以调用方法而不是LINQ查询语句。
标准查询操作符 | 说 明 | 示 例 |
Where | 通过传入的lambda表达式筛选出集合中符合条件的所有元素并返回 |
List<int> list = new List<int>() { 2, 20, 50, 18, 85, 56 }; IEnumerable<int> res = list.Where(n => n > 40); |
OfType<TResult> | 筛选出集合中数据类型为TResult的所有元素并返回 |
var list = new ArrayList() { 20, "aaa", 40, "bbb", "ccc" }; IEnumerable<string> res = list.OfType<string>(); IEnumerable<int> res2 = list.OfType<int>(); |
Select | 投射操作符,用于将一个对象转换为另一个对象 |
List<int> list = new List<int>() { 10, 20, 30, 40 }; IEnumerable<Person> res = list.Select(n => new Person() { Age = n, Name = "" }); |
SelectMany | 将指定的函数的结果作为作为源数据投射到新的集合中 |
List<Teacher> list = new List<Teacher>(){ new Teacher(new List<Student>{ new Student(){Name = "001",Score = 10}, new Student(){Name = "002",Score = 20}, new Student(){Name = "003",Score=30}}){Name = "ls1",Age=20}, new Teacher(new List<Student>(){ new Student(){Name = "004",Score=40}, new Student(){Name = "005",Score=50}}){Name = "ls2",Age = 30}, new Teacher(new List<Student>(){ new Student(){Name= "006",Score=60}, new Student(){Name = "007",Score=70}}){Name = "ls3",Age = 40} }; var res = list.SelectMany(t => t.list, (t, s) => new { TName = t.Name, TAge = t.Age, SName = s.Name, SScore = s.Score }); foreach (var item in res) { Console.WriteLine(item.TName + "--" + item.TAge + "--" + item.SName + "--" + item.SScore); } |
OrderBy | 根据传入的lambda表达式对集合中的元素进行排序(升序) |
List<int> list = new List<int>() { 2, 20, 13, 30, 29, 50, 23 }; List<Person> pList = new List<Person>() { new Person() { Name = "aa", Age = 20 }, new Person() { Name = "bb", Age = 13 } }; IEnumerable<int> res = list.OrderBy(n => n); IEnumerable<Person> pRes = pList.OrderBy(p => p.Age); |
ThenBy | 再次根据传入的lambda表达式对集合中的元素进行排序(升序) |
List<Person> list = new List<Person>() { new Person() { Name = "aa", Age = 20 }, new Person() { Name = "bb", Age = 13 } }; IEnumerable<Person> res = list.OrderBy(p => p.Age).ThenBy(p => p.Name); |
OrderByDescending | 根据传入的lambda表达式对集合中的元素进行排序(降序) |
List<Person> list = new List<Person>() { new Person() { Name = "aa", Age = 20 }, new Person() { Name = "bb", Age = 13 } }; IEnumerable<Person> res = list.OrderByDescending(p => p.Age); |
ThenByDescending | 再次根据传入的lambda表达式对集合中的元素进行排序(降序) |
List<Person> list = new List<Person>() { new Person() { Name = "aa", Age = 20 }, new Person() { Name = "bb", Age = 13 } }; IEnumerable<Person> res = list.OrderByDescending(p => p.Age).ThenByDescending(p => p.Name); |
Reverse | 翻转集合中元素的顺序(无返回值) |
1 List<int> list = new List<int>() { 10, 20, 30, 40, 50 }; 2 list.Reverse();//全部翻转 3 list.Reverse(2, 3);//从索引为2的元素开始,翻转后边3个元素的顺序 |
Join | 连接操作符,通过指定的键合并不直接相关的集合 |
List<Person> list = new List<Person>() { new Person() {ID=1, Name = "aa", Age = 20 }, new Person() {ID=2, Name = "bb", Age = 13 } }; List<PersonInfo> pList = new List<PersonInfo>() { new PersonInfo() { ID = 1, Address = "......" }, new PersonInfo() { ID = 2, Address = "******" } }; var res =list.Join(pList, p => p.ID, pi => pi.ID, (p, pi) => new { ID = p.ID, Name = p.Name, Age = p.Age, Address = pi.Address }); |
GroupBy | 根据传入的lambda表达式对集合中的元素进行分组 |
List<Person> list = new List<Person>() { new Person() { ID = 1, Name = "aa", Age = 20 }, new Person() { ID = 2, Name = "bb", Age = 13 }, new Person() { ID = 3, Name = "cc", Age = 20 } }; IEnumerable<IGrouping<int, Person>> res = list.GroupBy(p => p.Age); foreach (var item in res) { Console.WriteLine(item.Key); } |
ToLookup | 通过创建一个一对多字典来组合元素 |
List<int> list = new List<int>() { 10, 20, 30, 40, 50, 20, 40, 20, 40 }; //IEnumerable<IGrouping<int, int>> res = list.GroupBy(a => a);//最终结果中不包含元素20 ILookup<int, int> res = list.ToLookup(n => n);//最终结果包含元素20 list.RemoveAll(n => n == 20); foreach (IGrouping<int, int> item in res) { Console.WriteLine("************" + item.Key + "*****************"); foreach (int i in item) { Console.WriteLine(i); } } |
Any | 返回集合中是否包含满足指定条件的元素 |
List<Person> list = new List<Person>() { new Person() { ID = 1, Name = "aa", Age = 20 }, new Person() { ID = 2, Name = "bb", Age = 13 }, new Person() { ID = 3, Name = "cc", Age = 20 } }; Console.WriteLine(list.Any());//集合中包含元素,返回True Console.WriteLine(list.Any(p => p.Age > 10));//集合中包含Age大于10的元素,返回True Console.WriteLine(list.Any(p => p.Age > 20));//集合中包含Age大于20的元素,返回False |
All | 判断集合中所有元素是否满足指定条件 |
List<Person> list = new List<Person>() { new Person() { ID = 1, Name = "aa", Age = 20 }, new Person() { ID = 2, Name = "bb", Age = 13 }, new Person() { ID = 3, Name = "cc", Age = 20 } }; Console.WriteLine(list.All(p => p.Age > 10));//集合中所有元素的Age值都大于10,返回True Console.WriteLine(list.All(p => p.Age > 15));//集合中所有元素的Age值都大于15,返回False |
Contains | 判断集合元素中是否包含指定的值 |
List<int> list = new List<int>() { 10, 20, 30, 40, 50 }; Console.WriteLine(list.Contains(30));//判断集合元素中是否包含30,返回True |
Take | 从集合中获取指定个数的元素 |
List<int> list = new List<int>() { 10, 20, 30, 40, 50 }; IEnumerable<int> res = list.Take(3); |
Skip | 跳过指定个数的元素 |
List<int> list = new List<int>() { 10, 20, 30, 40, 50 }; IEnumerable<int> res = list.Skip(2).Take(3);//跳过3个元素,获取后边的3个元素 |
TakeWhile | 依次获取集合中满足条件的元素,直到不满足条件时停止 |
List<int> list = new List<int>() { 10, 20, 30, 10, 50 }; IEnumerable<int> res = list.TakeWhile(n => n > 15);//结果res中没有元素,因为集合list中的第一个元素不满足条件,后边的元素就没有进行判断 IEnumerable<int> res2 = list.TakeWhile(n => n < 30);//结果为10,20;当判断都集合中的第3个元素时,不满足条件,后边的元素就不进行判断 IEnumerable<int> res3 = list.TakeWhile(n => n >= 10);//结果为10,20,30,10,50 |
SkipWhile | 依次跳过集合中满足条件的元素,直到不满足条件时停止 |
List<int> list = new List<int>() { 10, 20, 30, 10, 50 }; IEnumerable<int> res = list.SkipWhile(n => n < 30).Take(2);//结果为30,10 |
Distinct | 返回集合中非重复的元素 |
List<int> list = new List<int>() { 10, 20, 30, 10, 50 }; IEnumerable<int> res = list.Distinct();//结果为10,20,30,50 |
Union | 返回两个集合的并集 |
List<int> list = new List<int>() { 10, 20, 30, 10, 50 }; List<int> list2 = new List<int>() { 20, 15, 40, 60 }; IEnumerable<int> res = list.Union(list2);//结果为10,20,30,50,15,40,60 |
Intersect | 返回两个集合同时包含的元素 |
List<int> list = new List<int>() { 10, 20, 30, 10, 50 }; List<int> list2 = new List<int>() { 20, 15, 40, 60 }; IEnumerable<int> res = list.Intersect(list2);//结果为20 |
Except | 返回集合中存在,并且传入集合中不存在的元素 |
List<int> list = new List<int>() { 10, 20, 30, 10, 50 }; List<int> list2 = new List<int>() { 20, 15, 40, 60 }; IEnumerable<int> res = list.Except(list2);//结果为10,30,50 |
Zip | 将两个结合合并为一个 |
List<int> list = new List<int>() { 10, 20, 30, 10, 50 }; List<int> list2 = new List<int>() { 20, 15, 40, 60, 30 }; IEnumerable<int> res = list.Zip(list2, (n, p) => n + p);//结果为30,35,70,70,80 |
First | 返回集合中第一个满足指定条件的元素 |
List<int> list = new List<int>() { 10, 20, 30, 10, 50 }; Console.WriteLine(list.First());//10 Console.WriteLine(list.First(n => n > 20));//30 |
FirstOrDefault | 返回集合中满足条件的第一个元素,如果所有元素都不满足条件求返回默认值 |
List<Person> pList = new List<Person>() { new Person() { ID = 1, Name = "aa", Age = 20 }, new Person() { ID = 2, Name = "bb", Age = 13 }, new Person() { ID = 3, Name = "cc", Age = 20 } }; List<int> list = new List<int>() { 10, 20, 30, 10, 50 }; Console.WriteLine(list.First());//10 Console.WriteLine(list.FirstOrDefault());//10 |
Last | 返回集合中最后一个满足指定条件的元素 |
List<int> list = new List<int>() { 10, 20, 30, 40, 50 }; Console.WriteLine(list.Last());//50 Console.WriteLine(list.Last(n => n < 40));//30 |
LastOrDefault | 返回集合中满足条件的最后一个元素,如果所有元素都不满足条件求返回默认值 |
List<Person> pList = new List<Person>() { new Person() { ID = 1, Name = "aa", Age = 20 }, new Person() { ID = 2, Name = "bb", Age = 13 }, new Person() { ID = 3, Name = "cc", Age = 20 } }; List<int> list = new List<int>() { 10, 20, 30, 40, 50 }; Console.WriteLine(list.Last());//50 Console.WriteLine(list.LastOrDefault());//50 Console.WriteLine(list.LastOrDefault(n => n < 40));//30 Console.WriteLine(list.LastOrDefault(n => n > 100));//0 Console.WriteLine(pList.LastOrDefault(p => p.Age > 30));//Null |
ElementAt | 返回指定索引处的元素 |
List<int> list = new List<int>() { 10, 20, 30, 40, 50 }; Console.WriteLine(list.ElementAt(2));//30 |
ElementAtOrDefault | 返回指定索引处的元素,如果索引超出范围,则返回默认值 |
List<Person> pList = new List<Person>() { new Person() { ID = 1, Name = "aa", Age = 20 }, new Person() { ID = 2, Name = "bb", Age = 13 }, new Person() { ID = 3, Name = "cc", Age = 20 } }; List<int> list = new List<int>() { 10, 20, 30, 40, 50 }; Console.WriteLine(list.ElementAtOrDefault(2));//30 Console.WriteLine(list.ElementAtOrDefault(10));//0 Console.WriteLine(pList.ElementAtOrDefault(10));//Null |
Single | 返回集合中满足指定条件的唯一一个元素,如果有多个元素满足条件,则会引发异常 |
List<int> list = new List<int>() { 10, 20, 30, 40, 50 }; Console.WriteLine(list.Single(n => n > 40));//50 Console.WriteLine(list.Single(n => n > 30));//异常:序列包含一个以上的匹配元素 |
SingleOrDefault | 返回集合中满足指定条件的唯一一个元素,如果集合为空或者集合中没有满足条件的元素,则返回默认值 |
List<int> list = new List<int>(); List<int> list2 = new List<int>() { 10, 20, 30, 40, 50 }; Console.WriteLine(list.SingleOrDefault(n => n > 50));//0 Console.WriteLine(list2.SingleOrDefault(n => n > 50));//0 Console.WriteLine(list2.SingleOrDefault(n => n > 30));//异常:序列包含一个以上的匹配元素 |
Count | 返回集合中满足指定条件的元素个数 |
List<int> list = new List<int>() { 10, 20, 30, 40, 50 }; Console.WriteLine(list.Count(n => n > 50));//0 Console.WriteLine(list.Count(n => n >= 10));//5 |
Sum | 返回集合中所有元素的和 |
List<int> list = new List<int>() { 10, 20, 30, 40, 50 }; Console.WriteLine(list.Sum());//150 Console.WriteLine(list.Sum(n => n * 10 + 1));//1505 |
Min | 返回集合中所有元素的最小值 |
List<int> list = new List<int>() { 10, 20, 30, 40, 50 }; Console.WriteLine(list.Min());//10 Console.WriteLine(list.Min(n => n % 3));//0 |
Max | 返回集合中所有元素的最大值 |
List<int> list = new List<int>() { 10, 20, 30, 40, 50 }; Console.WriteLine(list.Max());//50 Console.WriteLine(list.Max(n => n % 3));//2 |
Average | 返回集合中元素的平均值 |
List<int> list = new List<int>() { 10, 20, 30, 40, 50 }; Console.WriteLine(list.Average());//30 Console.WriteLine(list.Average(n => n * 10+1));//301 |
Aggregate | 通过指定的函数对结合中的元素进行累加操作 |
List<int> list = new List<int>() { 10, 20, 30, 40, 50 }; List<string> list2 = new List<string>() { "I", "am", "ZhangSan", "!" }; int sum = list.Aggregate((a, b) => a + b); string res = list2.Aggregate((s1, s2) => s1 + " " + s2); Console.WriteLine(sum);//150 Console.WriteLine(res);//I am ZhangSan ! |
ToArray | 将集合中的元素复制到一个数组中,并返回该数组 |
List<int> list = new List<int>() { 10, 20, 30, 40, 50 }; int[] arr = list.ToArray(); |
AsEnumerable | 将集合转换为一个IEnumerable对象 |
List<int> list = new List<int>() { 10, 20, 30, 40, 50 }; IEnumerable<int> res = list.AsEnumerable(); foreach (int i in res) { Console.WriteLine(i); } |
ToList | 将操作对象转换为集合 |
1 int[] arr = new int[] { 10, 20, 30, 40, 50 }; 2 arr.ToList(); |
ToDictionary | 将集合转换成字典对象 |
List<int> list = new List<int>() { 10, 20, 30, 40, 50 }; Dictionary<int, int> res = list.ToDictionary(n => n / 10); foreach (int item in res.Keys) { Console.WriteLine(item + "---" + res[item]); } |
Cast<TResult> | 该方法通过提供必要的类型信息,是非泛型集合可以调用标准查询操作符 |
ArrayList arr = new ArrayList() { "ff", "as" };//ArrayList类没有实现泛型接口IEnumerable<T>(实现了IEnumerable接口),所以无法使用Where()、Select()等标准查询操作符 Enumerable<string> res = arr.Cast<string>().Select(a => a += "*");//通过Cast<T>转化之后就可以使用标准查询操作符 |
DefaultIfEmpty | 返回集合中的元素,如果集合为空,则返回指定的默认值 |
List<int> list = new List<int>(); List<int> list2 = new List<int>() { 10, 20, 30, 40, 50 }; IEnumerable<int> res = list.DefaultIfEmpty(2); IEnumerable<int> res2 = list.DefaultIfEmpty(2); |
Empty | 返回一个元素类型为指定类型的空集合 |
1 IEnumerable<int> res = Enumerable.Empty<int>(); 2 Console.WriteLine(res.Count()); |
Range | 返回一个指定范围内的整数的序列 |
IEnumerable<int> res = Enumerable.Range(10, 10); foreach (int item in res) { Console.WriteLine(item); } |
Repeat | 生成一个包含重复值的序列 |
IEnumerable<string> res = Enumerable.Repeat("abc", 10); foreach (string item in res) { Console.WriteLine(item); } |