• 集合访问中的LINQ查询表达式与普通方法对比


    C# 中集合的概念不仅指的是System.Collection和System.Collection.Generic集合中的结合类型,实际上其他数据也可看作集合,如XML文件,数据库,数组都是集合,高效地集合操作能大大提高开发效率,C#中对于集合的操作希望做到尽量简单,统一,.NET Framework 3.5种引入的Linq(语言集成查询)实现了这一功能。

    下面我们以无序的List为例,来体验linq查询表达式相对于普通集合查询的优越性。

    先声明一个Book类:

    1 class Book
    2 {
    3     public string BookName { get; set; }
    4     public int PublishYear { get; set; }
    5     public string Author { get; set; }
    6 }
    View Code

    然后初始化一个List<Book>:

     1 List<Book> bookInstances=new List<Book>
     2 {
     3     new Book
     4     {
     5         BookName="Windows Phone 应用程序开发",
     6         PublishYear =2012,
     7         Author="李春旭"
     8     },
     9     new Book
    10     {
    11         BookName="Silverlight高级编程",
    12         PublishYear=2011,
    13         Author="李春旭"
    14     },
    15     new Book
    16     {
    17         BookName=".NET高级程序设计",
    18         PublishYear=2010,
    19         Author="李春旭"
    20     },
    21     new Book
    22     {
    23         BookName="精通Android应用程序",
    24         PublishYear=2010,
    25         Author="刘泽宏"
    26     }
    27 };
    View Code

    我们需要完成的三个任务:

    1. 查找书名为《.NET高级程序设计》的元素。
    2. 统计每个作者写书的数量。
    3. 找出每个作者出版的最后一本书。

    一 : 普通方法

    主要依靠对集合的循环遍历。

    Task 1:

     1 static void Task1()
     2 {
     3     Console.WriteLine("===查找元素书名为《.NET高级程序设计》的书=======");
     4     Book theSpecialBook = null;
     5     foreach (Book item in books)
     6     {
     7         if (item.BookName.Equals(".NET高级程序设计"))
     8         {
     9             theSpecialBook = item;
    10             break;
    11         }
    12     }
    13     Console.WriteLine(theSpecialBook.BookName);
    14     Console.WriteLine(theSpecialBook.Author);
    15     Console.WriteLine(theSpecialBook.PublishYear);
    16     Console.WriteLine();
    17 }
    View Code

    Task 2:

     1 static void Task2()
     2 {
     3     Console.WriteLine("===统计每个作者共写书的数量======");
     4     Dictionary<string, int> bookCount = new Dictionary<string, int>();
     5     foreach (Book item in books)
     6     {
     7         int bookNum = 0;
     8         if (bookCount.TryGetValue(item.Author, out bookNum))
     9         {
    10             bookNum++;
    11             bookCount[item.Author] = bookNum;
    12         }
    13         else
    14         {
    15             bookCount.Add(item.Author, 1);
    16         }
    17     }
    18     foreach (string key in bookCount.Keys)
    19     {
    20         Console.Write(key);
    21         Console.WriteLine("	" + bookCount[key]);
    22     }
    23     Console.WriteLine();
    24 }
    View Code

    Task 3:

     1 static void Task3()
     2 {
     3     Console.WriteLine("===每个作者出版的最后一本书=====");
     4     Dictionary<string, Book> lastBookList = new Dictionary<string, Book>();
     5     foreach (Book item in books)
     6     {
     7         Book temp = null;
     8         if (lastBookList.TryGetValue(item.Author, out temp))
     9         {
    10             if (item.PublishYear > temp.PublishYear)
    11             {
    12                 lastBookList[item.Author] = item;
    13             }
    14         }
    15         else
    16         {
    17             lastBookList.Add(item.Author, item);
    18         }
    19     }
    20 
    21     foreach (string key in lastBookList.Keys)
    22     {
    23         Console.WriteLine(key);
    24         Console.WriteLine("	" + lastBookList[key].BookName);
    25         Console.WriteLine("	" + lastBookList[key].PublishYear);
    26     }
    27 }
    View Code

    至此,我们发现上述对集合的操作无外乎是遍历,区别仅是遍历的条件,次数和遍历过程中保存临时变量的内容和条件的不同,这种操作方式相对不够直观和易于理解。

    二:Linq查询表达式

    Task 1:

     1 static void Task1()
     2 {
     3     Console.WriteLine("===查找元素书名为《.NET高级程序设计》的书=======");
     4     IEnumerable<Book> items =
     5         (from c in books where c.BookName.Equals(".NET高级程序设计") select c);
     6     foreach (Book item in items)
     7     {
     8         Console.WriteLine(item.BookName);                
     9         Console.WriteLine(item.Author);
    10         Console.WriteLine(item.PublishYear);
    11         Console.WriteLine();
    12     }
    13 }
    View Code

    Task 2:

     1 static void Task2()
     2 {
     3     Console.WriteLine("===统计每个作者共写书的数量======");
     4     //通过group按作者名字进行分组,然后统计每组的数量
     5     var items = from c in books
     6                 group c by c.Author into d
     7                 select new              //分组之后选择出一个匿名类,使用select将数据投射为另一种类型
     8                 {                       //该匿名类有两个属性,
     9                     d.Key,              //1.作者名字
    10                     Count = d.Count()   //2.书籍的数量
    11                 };                      //相对于使用Dictionary来保存更加简便和直接。
    12     foreach (var item in items)
    13     {
    14         Console.Write(item.Key);
    15         Console.WriteLine("	"+item.Count);
    16     }
    17     Console.WriteLine();
    18 }
    View Code

    Task 3:

     1 static void Task3()
     2 {
     3     Console.WriteLine("===每个作者出版的最后一本书=====");
     4     var lastBooks = from c in books
     5                     group c by c.Author into d
     6                     let maxPubYear=d.Max<Book>(item => item.PublishYear)
     7                     select new
     8                     {
     9                         d.Key,
    10                         PublishYear =maxPubYear,
    11                         LastBook = from e in books  
    12                                    where e.PublishYear.Equals(maxPubYear)&&e.Author.Equals(d.Key)
    13                                    select e.BookName
    14                     };
    15     foreach (var item in lastBooks)
    16     {
    17         Console.WriteLine(item.Key);
    18         Console.WriteLine("	"+item.LastBook.First());
    19         Console.WriteLine("	"+item.PublishYear);
    20     }
    21 }
    View Code

    从上面可以看出,使用Linq,只需要一句话就能完成多行代码才能完成的功能,并且形式上更容易理解,不需要去看循环的逻辑,判断条件,循环结束条件等逻辑判断,而且不需要去设计临时变量,不用考虑如何保存遍历的结果。

    使用Linq访问集合实际上是一种函数式编程,实现上述任务本质上还是调用了集合类实现的排序,查找等算法,Linq只是对相应的函数调用做了一个更易理解,更不易出错的语法描述。

    完整的项目和代码可在此处下载。

  • 相关阅读:
    DOM事件模型
    Javascript 跨域
    浏览器内核及差异
    对WEB标准的理解
    SVN权限解析规则详解
    一款成熟的前端框架——Bootstrap
    终于可以发文了
    一些感想
    Linux升级nodejs及多版本管理
    zepto 自定义build
  • 原文地址:https://www.cnblogs.com/fordwayne/p/3287476.html
Copyright © 2020-2023  润新知