zoukankan      html  css  js  c++  java
  • LINQ标准查询运算符执行方式-流式处理

    记录LINQ标准查询运算符的学习

    LINQ的延迟执行方式分两种,一种是流式处理,另一种是非流式处理。流式处理是指:当获取到的源元素足够计算时,就生成结果元素,不一定要获取全部源元素。

    ToAsEnumerable

    namespace ConsoleApp4
    {
        class Program
        {
            static void Main(string[] args)
            {           
                Clump<string> fruitClump =
                    new Clump<string> { "apple", "passionfruit", "banana",
                "mango", "orange", "blueberry", "grape", "strawberry" };
              
                // 调用 Clump's Where() method with a predicate.
                IEnumerable<string> query1 =
                    fruitClump.Where(fruit => fruit.Contains("o"));
    
                Console.WriteLine("query1 has been created.
    ");
                
                // 强迫使用 System.Linq.Enumerable 的 Where() 方法.
                IEnumerable<string> query2 =
                    fruitClump.AsEnumerable().Where(fruit => fruit.Contains("o"));
    
                // Display the output.
                Console.WriteLine("query2 has been created.");
            }
        }
        class Clump<T> : List<T>
        {
            // Custom implementation of Where().
            public IEnumerable<T> Where(Func<T, bool> predicate)
            {
                Console.WriteLine("In Clump's implementation of Where().");
                return Enumerable.Where(this, predicate);
            }
        }
    }

    Cast

    //ArrayList 继承的是IEnumerable 而非IEnumerable<T>
    System.Collections.ArrayList fruits = new System.Collections.ArrayList();
    fruits.Add("mango");
    fruits.Add("apple");
    fruits.Add("lemon");
    
    //OrderBy扩展的是IEnumerable<T>。因此通过Cast<T>转为IEnumerable<T>
    IEnumerable<string> query =
        fruits.Cast<string>().OrderBy(fruit => fruit).Select(fruit => fruit);
    
    foreach (string fruit in query)
    {
        Console.WriteLine(fruit);
    }            

     Concat 连接序列

    Pet[] cats = GetCats();
    Pet[] dogs = GetDogs();
    
    IEnumerable<string> query =
        cats.Select(cat => cat.Name).Concat(dogs.Select(dog => dog.Name));
    
    foreach (string name in query)
    {
        Console.WriteLine(name);
    }

    //用另一个select重载试试
    IEnumerable<string> query1 =
        cats.Select((pet, index) => { if (index == 2) { return pet.Name; } else { return ""; } })
        .Concat(dogs.Select(dog=>dog.Name))

    DefaultIfEmpty 如果序列为空,则返回一个具有默认值的单例类集合

    Pet defaultPet = new Pet { Name = "Default Pet", Age = 0 };
    
    List<Pet> pets1 =
        new List<Pet>{ new Pet { Name="Barley", Age=8 },
               new Pet { Name="Boots", Age=4 },
               new Pet { Name="Whiskers", Age=1 } };
    
    foreach (Pet pet in pets1.DefaultIfEmpty(defaultPet))
    {
        Console.WriteLine("Name: {0}", pet.Name);
    }
    
    List<Pet> pets2 = new List<Pet>();
    
    foreach (Pet pet in pets2.DefaultIfEmpty(defaultPet))
    {
        Console.WriteLine("
    Name: {0}", pet.Name);
    }           

    Distinct 返回元素不重复的元素,可以使用默认比较器,也可以传个新的

    Product product1 = new Product { Name = "apple", Code = 9 };
    Product[] products = { product1,
               new Product { Name = "orange", Code = 4 },
              product1,
               new Product { Name = "lemon", Code = 12 } };
    
    //在此处,使用默认比较器
    IEnumerable<Product> noduplicates = products.Distinct();
    
    //该不该生产当前结果元素,只需要判断之前的源元素有没有一样的,知道判断到有,就不生成
    foreach (var product in noduplicates)  
        Console.WriteLine(product.Name + " " + product.Code);

    Except 返回序列之间的差值

    double[] numbers1 = { 2.0, 2.0, 2.1, 2.2, 2.3, 2.3, 2.4, 2.5 };
    double[] numbers2 = { 2.2 };
    
    IEnumerable<double> onlyInFirstSet = numbers1.Except(numbers2);
    
    foreach (double number in onlyInFirstSet)
        Console.WriteLine(number);            

    GroupJoin 两个序列进行分组联接

    Person magnus = new Person { Name = "Hedlund, Magnus" };
    Person terry = new Person { Name = "Adams, Terry" };           
    
    Pet barley = new Pet { Name = "Barley", Owner = terry };
    Pet boots = new Pet { Name = "Boots", Owner = terry };
    Pet daisy = new Pet { Name = "Daisy", Owner = magnus };
    
    List<Person> people = new List<Person> { magnus, terry };
    List<Pet> pets = new List<Pet> { barley, boots, daisy };
    
    //Pet的Owner和Person关联
    var query =
        people.GroupJoin(pets,
                         person => person,
                         pet => pet.Owner,
                         (person, petCollection) =>
                             new
                             {
                                 OwnerName = person.Name,
                                 Pets = petCollection.Select(pet => pet.Name)
                             });
    
    foreach (var obj in query)
    {                
        Console.WriteLine("{0}:", obj.OwnerName);               
        foreach (string pet in obj.Pets)
        {
            Console.WriteLine("  {0}", pet);
        }
    }

    Intersect 求序列交集

    Product product = new Product { Name = "apple", Code = 5 };
    
    Product[] store1 = { product,
               new Product { Name = "orange", Code = 4 } };
    
    Product[] store2 = { product,
               new Product { Name = "lemon", Code = 12 } };
    
    //在这里 使用默认比较器求差值
    var products = store1.Intersect(store2); 
    
    foreach(var item in products)
    {
        Console.WriteLine(item.Name);
    }

    Join基于匹配建对序列的元素进行关联

    Person magnus = new Person { Name = "Hedlund, Magnus" };
    Person terry = new Person { Name = "Adams, Terry" };
    Person charlotte = new Person { Name = "Weiss, Charlotte" };
    
    Pet barley = new Pet { Name = "Barley", Owner = terry };
    Pet boots = new Pet { Name = "Boots", Owner = terry };
    Pet whiskers = new Pet { Name = "Whiskers", Owner = charlotte };
    Pet daisy = new Pet { Name = "Daisy", Owner = magnus };
    
    List<Person> people = new List<Person> { magnus, terry, charlotte };
    List<Pet> pets = new List<Pet> { barley, boots, whiskers, daisy };
    
    //pet的owner和person关联 
    var query =
        people.Join(pets,
                    person => person,
                    pet => pet.Owner,
                    (person, pet) =>
                        new { OwnerName = person.Name, Pet = pet.Name });
    
    foreach (var obj in query)
    {
        Console.WriteLine(
            "{0} - {1}",
            obj.OwnerName,
            obj.Pet);
    }

    OfType 根据指定类型筛选序列指定的元素

    System.Collections.ArrayList fruits = new System.Collections.ArrayList(4);
    fruits.Add("Mango");
    fruits.Add("Orange");
    fruits.Add("Apple");
    fruits.Add(3.0);
    fruits.Add("Banana");
    
    // Apply OfType() to the ArrayList.
    IEnumerable<string> query1 = fruits.OfType<string>();
    
    Console.WriteLine("Elements of type 'string' are:");
    foreach (string fruit in query1)
    {
        Console.WriteLine(fruit);
    }
    
    Console.WriteLine("Elements of type 'int' are:");
    IEnumerable<double> query2 = fruits.OfType<double>();
    foreach (var num in query2)
    {
        Console.WriteLine(num);
    }

     Range 生成指定范围内的序列

    IEnumerable<int> squares = Enumerable.Range(1, 10).Select(x => x * x);
    
    foreach (int num in squares)
    {
        Console.WriteLine(num);
    }

     Repeat生成一个包含重复值的序列

    IEnumerable<string> strings =
    Enumerable.Repeat("I like programming.", 15);
    
    foreach (String str in strings)
    {
        Console.WriteLine(str);
    }

    Select 将序列中的每个元素投影到新表单

    string[] fruits = { "apple", "banana", "mango", "orange",
              "passionfruit", "grape" };
    
    var query =
        fruits.Select((fruit, index) => new { index,str=fruit.Substring(0,index)});
    
    foreach (var obj in query)
    {
        Console.WriteLine("{0}", obj);
    }            

    SelectMany 将序列的每个元素投影到 IEnumerable<T> ,然后,每个元素投影到的结果序列合并成一个大的序列。

    PetOwner[] petOwners =
    {
      new PetOwner { Name="Higa",
          Pets = new List<string>{ "Scruffy", "Sam" } },
      new PetOwner { Name="Ashkenazi",
          Pets = new List<string>{ "Walker", "Sugar" } },
      new PetOwner { Name="Price",
          Pets = new List<string>{ "Scratches", "Diesel" } },
      new PetOwner { Name="Hines",
          Pets = new List<string>{ "Dusty" } }
    };
    
    //想要的结果,Higa养猪人都有哪些猪,排成一行行的结果。
    // {Owner=Higa, Pet=Scruffy}
    // {Owner=Higa, Pet=Sam}
    
    var query = petOwners.Where(owner=>owner.Name=="Higa")
        .SelectMany(owner => owner.Pets, (owner, pet) => new { owner = owner.Name, pet });
    foreach(var obj in query)
    {
        Console.WriteLine(obj);
    }           
    Skip 跳过指定数量的元素,返回一个剩下元素组成的新序列
    int[] grades = { 59, 82, 70, 56, 92, 98, 85 };
    
    IEnumerable<int> lowerGrades =
        grades.Skip(2);
    
    foreach (int grade in lowerGrades)
    {
        Console.WriteLine(grade);
    }
    
    //返回结果
    //70
    //56
    //92
    //98
    //85
    SkipWhile 当条件为true,前面的元素忽略,剩下的元素组成一个新序列。
    下面有坑,请注意。
    int[] grades = { 59, 82, 70, 56, 92, 98, 85 };
    
    IEnumerable<int> newGrades =
         grades.SkipWhile(grade => grade >= 80);
    
    foreach (int grade in newGrades)
    {
        Console.WriteLine(grade);
    }
    
    Console.WriteLine("
    ");
    
    //排序之后的跳过
    IEnumerable<int> lowerGrades =
         grades.OrderByDescending(g=>g).SkipWhile(grade => grade >= 80);
    
    foreach (int grade in lowerGrades)
    {
        Console.WriteLine(grade);
    }

    控制台输出结果:
    59
    82
    70
    56
    92
    98
    85

    70
    59
    5
    Take从序列的开头返回指定数量的相邻元素
    int[] grades = { 59, 82, 70, 56, 92, 98, 85 };
    
    IEnumerable<int> newGrades =
        grades.Take(3);
    
    foreach (int grade in newGrades)
    {
        Console.WriteLine(grade);
    }
    TakeWhile 只要指定的条件为 true,就会返回序列的元素,从开头开始取,直到不满足条件,剩下的元素也不返回了
    string[] fruits = { "apple", "banana", "mango", "orange",
              "passionfruit", "grape" };
    
    IEnumerable<string> query =
        fruits.TakeWhile(fruit => String.Compare("orange", fruit, true)!= 0);
    
    foreach (string fruit in query)
    {
        Console.WriteLine(fruit);
    }
    
    Console.WriteLine("
    ");
    
    IEnumerable<string> query1 =
        fruits.TakeWhile(fruit => String.Compare("apple", fruit, true) == 0);
    
    foreach (string fruit in query1)
    {
        Console.WriteLine(fruit);
    }
    
    /*
     输出结果:
    
     apple
     banana
     mango
    
     apple
    */

    Union 生成两个序列的并集

    跑了好些示例,发现只要通过标准运算符生成的元素如果要通过判断相等操作,都有比较器可以传入的函数。

    int[] ints1 = { 5, 3, 9, 7, 5, 9, 3, 7 };
    int[] ints2 = { 8, 3, 6, 4, 4, 9, 1, 0 };
    
    IEnumerable<int> union = ints1.Union(ints2);
    
    foreach (int num in union)
    {
        Console.Write("{0} ", num);
    }

    Where 基于条件筛选序列,太常用了。

    List<string> fruits =
        new List<string> { "apple", "passionfruit", "banana", "mango", 
                        "orange", "blueberry", "grape", "strawberry" };
    
    IEnumerable<string> query = fruits.Where(fruit => fruit.Length < 6);
    
    foreach (string fruit in query)
    {
        Console.WriteLine(fruit);
    }
    /*
     This code produces the following output:
    
     apple
     mango
     grape
    */
     
  • 相关阅读:
    线上项目部署
    day26 面向对象 单例模式总结
    阿里云服务器,更换操作系统步骤总结
    后端for循环补充
    前端,css
    django-admin 仿写stark组件action,filter筛选过滤,search查询
    7.20晚作业
    用户和群组管理
    7.19 晚作业
    目录和文件管理
  • 原文地址:https://www.cnblogs.com/bibi-feiniaoyuan/p/12378001.html
Copyright © 2011-2022 走看看