LINQ笔记&实例
- huuhghhgyg
- 6 min read
LINQ:语言继承查询
限制运算符 Where
where语句的基本示例
1int[] numbers = {5,4,1,3,9,8,6,7,2,0};
2var lowNums = from num in numbers
3 where num < 5
4 select num; // 只选择小于5的数字
筛选符合属性条件的元素
1var soldOutProducts = from prod in products
2 where prod.UnitsInStock == 0
3 select prod; // 从集合中选出符合属性的元素
用多个条件筛选元素
1var expensiveInStockProducts = from prod in products
2 where prod.UnitsInStock > 0 && prod.UnitPrice > 3.00M
3 select prod; // 从集合中选出符合上述两个条件的元素
基于元素在列表中位置的筛选
1string[] digits = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};
2var shortDigits = digits.Where((digit,index) => digit.Length < index);
3 // 其中,index为元素的位置下标(从0开始),digit为digits的子元素。
以…开始
使用AutoSuggestBox
控件
Xaml:
1<AutoSuggestBox Name="MyAutoSuggestBox"
2 QueryIcon="Find"
3 PlaceholderText="Search"
4 TextChanged="MyAutoSuggestBox_TextChanged"/>
C#
1private string[] selectionItems = new string[] {"Ferdinand", "Nigel", "Tag",...};
2
3private void MyAutoSuggestBox_TextChanged(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs e)
4{
5 var autoSuggestBox = (AutoSuggestBox)sender;
6 var fileterd = selectionItems.Where(p => p.StartWith(AutoSuggestBox.Text)).ToArray();
7 autoSuggestBox.ItemSource = filtered;
8}
投影(转换)运算符 Select
以下的例子展示了如何用select修改输入的元素序列。
1int[] numbers = {5,4,1,3,9,8,6,7,2,0};
2
3var numsPlusOne = from n in numbers
4 select n+1;
选择一个单独的属性
1var productNames = from p in products
2 select p.ProductName; // 选择了p的ProductName属性
用select
进行一些变换
1int[] numbers = {5,4,1,3,9,8,6,7,2,0}; // 数字序列
2string[] strings = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"}; // 单词序列
3
4var textNums = from n in numbers
5 select strings[n]; // 用数字序列的元素作为下标选择单词序列中的元素
选择匿名类型或元组
注意:创建新类型的时候,需要使用
new
关键字
1string[] words = { "aPPLE", "BlUeBeRrY", "cHeRry" };
2
3var upperLowerWords = from w in words
4 select new { Upper = w.ToUpper(), Lower = w.ToLower() };
5 // 生成的Upper和Lower里面分别是这些单词的大写和小写版本
6
7// 使用元组的方法(从C#7开始)
8var upperLowerWords = from w in words
9 select new { Upper: w.ToUpper(), Lower: w.ToLower() };
使用select
创建新类型
1int[] numbers = {5,4,1,3,9,8,6,7,2,0}; // 数字序列
2string[] strings = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"}; // 单词序列
3
4var digitOddEvens = from n in numbers
5 select new { Digit = strings[n], Even = (n % 2 == 0)};
6 // 创建了两个类型:
7 // Digit:对应数字的单词序列
8 // Even:偶数序列
选择属性的子集 我还没试,Try.NET坏了…😭
1var productInfos = from p in products
2 select (p.ProductName, p.Category, Price: p.UnitPrice);
3
4Console.WriteLine("Product Info:");
5foreach (var productInfo in productInfos)
6{
7 Console.WriteLine($"{productInfo.ProductName} is in the category {productInfo.Category} and costs {productInfo.Price} per unit.");
8}
用元素的index
对其进行选择
1int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
2var numsInPlace = numbers.Select((num, index) => (Num: num, InPlace: (num == index)));
3// 得到的numsInPlace中有Num和InPlace,其中InPlace为num==index的值
在多输入序列中进行选择
1int[] numbersA = { 0, 2, 4, 5, 6, 8, 9 };
2int[] numbersB = { 1, 3, 5, 7, 8 };
3
4var pairs = from a in numbersA
5 from b in numbersB
6 where a < b
7 select (a, b); // 符合条件的(a,b)对(pairs)
8
9Console.WriteLine("Pairs where a < b:");
10foreach (var pair in pairs)
11{
12 Console.WriteLine($"{pair.a} is less than {pair.b}");
13 // 把所有的a和所有的b逐个进行比较
14}
在相关的输入序列中进行选择
1var orders = from c in customers
2 from o in c.Orders
3 where o.Total < 500.00M
4 select (c.CustomerID, o.OrderID, o.Total);
5 // cutomers -> c:顾客
6 // c -> c.o:订单(与c相关联)
7 // c.o -> o:订单信息
带有Where的符合选择
1var orders = from c in customers
2 from o in c.Orders
3 where o.OrderDate >= new DateTime(1998, 1, 1)
4 select (c.CustomerID, o.OrderID, o.OrderDate);
Query Syntax 查询语法(分区运算符)
Take
n.Take(n);
获取前n个元素
1int[] numbers={5,4,3,2,1};
2var first3Numbers = numbers.Take(3); // First3Numbers是一个集合,有3个数
Take
也可以嵌套到其它查询语句中
1var first3WAOrders = (
2 from customer in customers
3 from order in cutomer.Orders
4 where customer.Region == "WA"
5 select (customer.CustomerID, order.OrderID, order.OrderDate)
6 .Take(3);
7) // 得到前3个
Skip
n.Skip(n)
跳过前n个元素
1int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
2var allButFirst4Numbers = numbers.Skip(4);
先查询,再在结果中跳过
1var waOrders = from cust in customers
2 from order in cust.Orders
3 where cust.Region == "WA"
4 select (cust.CustomerID, order.OrderID, order.OrderDate);
5
6var allButFirst2Orders = waOrders.Skip(2); // 查询完毕后,从查询结果中跳过前2个结果
TakeWhile
理解为While
循环下的Take()
。一旦不符合条件就停止。
1int[] numbers = {5,4,1,3,9,8,6,7,2,0};
2var firstNumbersLessThan6 = numbers.TakeWhile(n => n<6);
3 // 从开始一直Take(),直到n<6的条件不成立
用index
作为条件的TakeWhile
1int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
2var firstSmallNumbers = numbers.TakeWhile((n, index) => n >= index);
SkipWhile
以下例子只显示分数小于80的成绩。
1int[] grades = { 59, 82, 70, 56, 92, 98, 85 };
2
3IEnumerable<int> lowerGrades =
4 grades
5 .OrderByDescending(grade => grade)
6 .SkipWhile(grade => grade >= 80);
7
8Console.WriteLine("All grades below 80:");
9foreach (int grade in lowerGrades)
10{
11 Console.WriteLine(grade);
12}
13
14// This code produces the following output:
15
16// All grades below 80:
17// 70
18// 59
19// 56
使用n
和index
进行筛选
1int[] amounts = { 5000, 2500, 9000, 8000,
2 6500, 4000, 1500, 5500 };
3
4IEnumerable<int> query =
5 amounts.SkipWhile((amount, index) => amount > index * 1000);
6
7foreach (int amount in query)
8{
9 Console.WriteLine(amount);
10}
11
12
13// This code produces the following output:
14
15// 4000
16// 1500
17// 5500
排序运算符
orderby 升序
升序:0,1,2,…
使用orderby
根据宠物年龄进行升序排序
1class Pet
2{
3 public string Name { get; set; }
4 public int Age { get; set; }
5}
6
7public static void OrderByEx1()
8{
9 Pet[] pets = { new Pet { Name="Barley", Age=8 },
10 new Pet { Name="Boots", Age=4 },
11 new Pet { Name="Whiskers", Age=1 } };
12
13 // Sort the Pet objects in the array by Pet.Age.
14 IEnumerable<Pet> query =
15 pets.AsQueryable().OrderBy(pet => pet.Age);
16
17 foreach (Pet pet in query)
18 Console.WriteLine($"{pet.Name} - {pet.Age}");
19}
20
21// This code produces the following output:
22
23// Whiskers - 1
24// Boots - 4
25// Barley - 8
orderby descending
使用orderby
和descending
关键字对数字进行降序排序。
1double[] doubles = { 1.7, 2.3, 1.9, 4.1, 2.9 };
2
3var sortedDoubles = from d in doubles
4 orderby d descending // 注意descending的用法
5 select d;
6
7Console.WriteLine("The doubles from highest to lowest:");
序列操作
EqualAll
如果两个序列相同,返回True
1var wordsA = new string[] { "cherry", "apple", "blueberry" };
2var wordsB = new string[] { "cherry", "apple", "blueberry" };
3
4bool match = wordsA.SequenceEqual(wordsB);
5
6Console.WriteLine($"The sequences match: {match}"); //True
7// 如果以上两个序列中的元素顺序进行了调换,输出值则为False
Zip
1int[] vectorA = { 0, 2, 4, 5, 6 };
2int[] vectorB = { 1, 3, 5, 7, 8 };
3
4int dotProduct = vectorA.Zip(vectorB, (a, b) => a * b).Sum();
5 // 把A中的元素和B中的对应元素进行操作。
6 // Sum()为求和
7
8Console.WriteLine($"Dot product: {dotProduct}");
9// Dot product:109
Query(查询)执行模式
懒惰执行
如果数据经常变化,可以考虑使用“懒惰查询”,需要时再进行查询。
1int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
2
3int i = 0;
4var q = from n in numbers
5 select ++i; //i: 0 → 1
6
7// Note, the local variable 'i' is not incremented
8// until each element is evaluated (as a side-effect):
9// 直到每个值被使用时才执行++i
10foreach (var v in q)
11{
12 Console.WriteLine($"v = {v}, i = {i}");
13 // ++i在这里才被执行并存入v中。
14 // 这里的i是原来的i(int i=0时定义的)
15}
如果把foreach
再完整执行一遍,v
和i
的值将会到达20
急迫执行
当数据不会变时使用“急迫执行”,因为再次查询数据也不会变。
1// Methods like ToList() cause the query to be
2// executed immediately, caching the results.
3// 类似ToList()的方法可以使query立即执行。
4
5int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
6
7int i = 0;
8var q = (from n in numbers
9 select ++i)
10 .ToList();
11
12// The local variable i has already been fully
13// incremented before we iterate the results:
14// 在输出结果之前,++i已经全部执行完了
15foreach (var v in q)
16{
17 Console.WriteLine($"v = {v}, i = {i}");
18}
如果把foreach
再完整执行一遍,i
的值仍然全为10,v
的值也不变