LINQ笔记&实例

Author Avatar
huuhghhgyg 3月 12, 2022
  • 在其它设备中阅读本文章

LINQ:语言继承查询

限制运算符 Where

where语句的基本示例

int[] numbers = {5,4,1,3,9,8,6,7,2,0};
var lowNums = from num in numbers
              where num < 5
              select num; // 只选择小于5的数字

筛选符合属性条件的元素

var soldOutProducts = from prod in products
                      where prod.UnitsInStock == 0
                      select prod; // 从集合中选出符合属性的元素

用多个条件筛选元素

var expensiveInStockProducts = from prod in products
                               where prod.UnitsInStock > 0 && prod.UnitPrice > 3.00M
                               select prod; // 从集合中选出符合上述两个条件的元素

基于元素在列表中位置的筛选

string[] digits = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};
var shortDigits = digits.Where((digit,index) => digit.Length < index);
                  // 其中,index为元素的位置下标(从0开始),digit为digits的子元素。

以…开始
使用AutoSuggestBox控件
Xaml:

<AutoSuggestBox Name="MyAutoSuggestBox" 
                QueryIcon="Find" 
                PlaceholderText="Search" 
                TextChanged="MyAutoSuggestBox_TextChanged"/>

C#

private string[] selectionItems = new string[] {"Ferdinand", "Nigel", "Tag",...};

private void MyAutoSuggestBox_TextChanged(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs e)
{
    var autoSuggestBox = (AutoSuggestBox)sender;
    var fileterd = selectionItems.Where(p => p.StartWith(AutoSuggestBox.Text)).ToArray();
    autoSuggestBox.ItemSource = filtered;
}

投影(转换)运算符 Select

以下的例子展示了如何用select修改输入的元素序列。

int[] numbers = {5,4,1,3,9,8,6,7,2,0};

var numsPlusOne = from n in numbers
                  select n+1;

选择一个单独的属性

var productNames = from p in products
                   select p.ProductName; // 选择了p的ProductName属性

select进行一些变换

int[] numbers = {5,4,1,3,9,8,6,7,2,0}; // 数字序列
string[] strings = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"}; // 单词序列

var textNums = from n in numbers
               select strings[n]; // 用数字序列的元素作为下标选择单词序列中的元素

选择匿名类型或元组

注意:创建新类型的时候,需要使用new关键字

string[] words = { "aPPLE", "BlUeBeRrY", "cHeRry" };

var upperLowerWords = from w in words
                      select new { Upper = w.ToUpper(), Lower = w.ToLower() };
                      // 生成的Upper和Lower里面分别是这些单词的大写和小写版本

// 使用元组的方法(从C#7开始)
var upperLowerWords = from w in words
                      select new { Upper: w.ToUpper(), Lower: w.ToLower() };

使用select创建新类型

int[] numbers = {5,4,1,3,9,8,6,7,2,0}; // 数字序列
string[] strings = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"}; // 单词序列

var digitOddEvens = from n in numbers
                    select new { Digit = strings[n], Even = (n % 2 == 0)}; 
                    // 创建了两个类型:
                    //  Digit:对应数字的单词序列
                    //  Even:偶数序列

选择属性的子集
我还没试,Try.NET坏了…😭

var productInfos = from p in products
                   select (p.ProductName, p.Category, Price: p.UnitPrice);

Console.WriteLine("Product Info:");
foreach (var productInfo in productInfos)
{
    Console.WriteLine($"{productInfo.ProductName} is in the category {productInfo.Category} and costs {productInfo.Price} per unit.");
}

用元素的index对其进行选择

int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
var numsInPlace = numbers.Select((num, index) => (Num: num, InPlace: (num == index)));
// 得到的numsInPlace中有Num和InPlace,其中InPlace为num==index的值

在多输入序列中进行选择

int[] numbersA = { 0, 2, 4, 5, 6, 8, 9 };
int[] numbersB = { 1, 3, 5, 7, 8 };

var pairs = from a in numbersA
            from b in numbersB
            where a < b
            select (a, b); // 符合条件的(a,b)对(pairs)

Console.WriteLine("Pairs where a < b:");
foreach (var pair in pairs)
{
    Console.WriteLine($"{pair.a} is less than {pair.b}");
    // 把所有的a和所有的b逐个进行比较
}

在相关的输入序列中进行选择

var orders = from c in customers
             from o in c.Orders
             where o.Total < 500.00M
             select (c.CustomerID, o.OrderID, o.Total);
             // cutomers -> c:顾客
             // c -> c.o:订单(与c相关联)
             // c.o -> o:订单信息

带有Where的符合选择

var orders = from c in customers
             from o in c.Orders
             where o.OrderDate >= new DateTime(1998, 1, 1)
             select (c.CustomerID, o.OrderID, o.OrderDate);

Query Syntax 查询语法(分区运算符)

Take

n.Take(n);获取前n个元素

int[] numbers={5,4,3,2,1};
var first3Numbers = numbers.Take(3); // First3Numbers是一个集合,有3个数

Take也可以嵌套到其它查询语句中

var first3WAOrders = (
    from customer in customers
    from order in cutomer.Orders
    where customer.Region == "WA"
    select (customer.CustomerID, order.OrderID, order.OrderDate)
    .Take(3);
) // 得到前3个

Skip

n.Skip(n)跳过前n个元素

int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
var allButFirst4Numbers = numbers.Skip(4);

先查询,再在结果中跳过

var waOrders = from cust in customers
               from order in cust.Orders
               where cust.Region == "WA"
               select (cust.CustomerID, order.OrderID, order.OrderDate);

var allButFirst2Orders = waOrders.Skip(2); // 查询完毕后,从查询结果中跳过前2个结果

TakeWhile

理解为While循环下的Take()。一旦不符合条件就停止。

int[] numbers = {5,4,1,3,9,8,6,7,2,0};
var firstNumbersLessThan6 = numbers.TakeWhile(n => n<6);
                        // 从开始一直Take(),直到n<6的条件不成立

index作为条件的TakeWhile

int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
var firstSmallNumbers = numbers.TakeWhile((n, index) => n >= index);

SkipWhile

以下例子只显示分数小于80的成绩。

int[] grades = { 59, 82, 70, 56, 92, 98, 85 };

IEnumerable<int> lowerGrades =
    grades
    .OrderByDescending(grade => grade)
    .SkipWhile(grade => grade >= 80);

Console.WriteLine("All grades below 80:");
foreach (int grade in lowerGrades)
{
    Console.WriteLine(grade);
}

// This code produces the following output:

// All grades below 80:
// 70
// 59
// 56

使用nindex进行筛选

int[] amounts = { 5000, 2500, 9000, 8000,
                    6500, 4000, 1500, 5500 };

IEnumerable<int> query =
    amounts.SkipWhile((amount, index) => amount > index * 1000);

foreach (int amount in query)
{
    Console.WriteLine(amount);
}


// This code produces the following output:

// 4000
// 1500
// 5500

排序运算符

orderby 升序

升序:0,1,2,…
使用orderby根据宠物年龄进行升序排序

class Pet
{
    public string Name { get; set; }
    public int Age { get; set; }
}

public static void OrderByEx1()
{
    Pet[] pets = { new Pet { Name="Barley", Age=8 },
                   new Pet { Name="Boots", Age=4 },
                   new Pet { Name="Whiskers", Age=1 } };

    // Sort the Pet objects in the array by Pet.Age.
    IEnumerable<Pet> query =
        pets.AsQueryable().OrderBy(pet => pet.Age);

    foreach (Pet pet in query)
        Console.WriteLine($"{pet.Name} - {pet.Age}");
}

// This code produces the following output:

// Whiskers - 1
// Boots - 4
// Barley - 8

orderby descending

使用orderbydescending关键字对数字进行降序排序。

double[] doubles = { 1.7, 2.3, 1.9, 4.1, 2.9 };

var sortedDoubles = from d in doubles
                    orderby d descending // 注意descending的用法
                    select d;

Console.WriteLine("The doubles from highest to lowest:");

序列操作

EqualAll

如果两个序列相同,返回True

var wordsA = new string[] { "cherry", "apple", "blueberry" };
var wordsB = new string[] { "cherry", "apple", "blueberry" };

bool match = wordsA.SequenceEqual(wordsB);

Console.WriteLine($"The sequences match: {match}"); //True
// 如果以上两个序列中的元素顺序进行了调换,输出值则为False

Zip

int[] vectorA = { 0, 2, 4, 5, 6 };
int[] vectorB = { 1, 3, 5, 7, 8 };

int dotProduct = vectorA.Zip(vectorB, (a, b) => a * b).Sum();
                            // 把A中的元素和B中的对应元素进行操作。
                            // Sum()为求和

Console.WriteLine($"Dot product: {dotProduct}");
// Dot product:109

Query(查询)执行模式

懒惰执行

如果数据经常变化,可以考虑使用“懒惰查询”,需要时再进行查询。

int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };

int i = 0;
var q = from n in numbers
        select ++i; //i: 0 → 1

// Note, the local variable 'i' is not incremented
// until each element is evaluated (as a side-effect):
// 直到每个值被使用时才执行++i
foreach (var v in q)
{
    Console.WriteLine($"v = {v}, i = {i}");
    // ++i在这里才被执行并存入v中。
    // 这里的i是原来的i(int i=0时定义的)
}

如果把foreach再完整执行一遍,vi的值将会到达20

急迫执行

当数据不会变时使用“急迫执行”,因为再次查询数据也不会变。

// Methods like ToList() cause the query to be
// executed immediately, caching the results.
// 类似ToList()的方法可以使query立即执行。

int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };

int i = 0;
var q = (from n in numbers
         select ++i)
         .ToList();

// The local variable i has already been fully
// incremented before we iterate the results:
// 在输出结果之前,++i已经全部执行完了
foreach (var v in q)
{
    Console.WriteLine($"v = {v}, i = {i}");
}

如果把foreach再完整执行一遍,i的值仍然全为10,v的值也不变

link
本文链接:
发文时间
3月 12, 2022
请遵循协议