<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      LINQ之路14:LINQ Operators之排序和分組(Ordering and Grouping)

      本篇繼續LINQ Operators的介紹,這里要討論的是LINQ中的排序和分組功能。LINQ的排序操作符有:OrderBy, OrderByDescending, ThenBy, 和ThenByDescending,他們返回input sequence的排序版本。分組操作符GroupBy把一個平展的輸入sequence進行分組存放到輸出sequence中。

      排序/Ordering

      IEnumerable<TSource>→IOrderedEnumerable<TSource>

      Operator

      說明

      SQL語義

      OrderBy, ThenBy

      對一個sequence按升序排序

      ORDER BY ...

      OrderByDescending, ThenByDescending

      對一個sequence按降序排序

      ORDER   BY ... DESC

      Reverse

      按倒序返回一個sequence

      Exception thrown

      排序操作符以不同順序返回相同的elements。

      OrderBy, OrderByDescending, ThenBy, 和ThenByDescending

      OrderBy和OrderByDescending的參數

      參數

      類型

      Input sequence

      IEnumerable<TSource>

      鍵選擇器/Key selector

      TSource => TKey

       

      Return type = IOrderedEnumerable<TSource>

      ThenBy和ThenByDescending參數

      參數

      類型

      Input sequence

      IOrderedEnumerable <TSource>

      鍵選擇器/Key selector

      TSource => TKey

       

      查詢表達式語法

                  orderby expression1 [descending] [, expression2 [descending] ... ]

      簡介

      OrderBy返回input sequence的排序版本,使用鍵選擇器來進行排序比較。請看下面的示例:

                  string[] names = { "Tom", "Dick", "Harry", "Mary", "Jay" };

      //對names sequence按字母順序排序:
      IEnumerable<string> query = names.OrderBy (s => s);
      // Result: { "Dick", "Harry", "Jay", "Mary", "Tom" };

      //按姓名長度進行排序
      IEnumerable<string> query = names.OrderBy (s => s.Length);
      // Result: { "Jay", "Tom", "Mary", "Dick", "Harry" };

      對于擁有相同排序鍵值的elements來說,他們的相對位置是不確定的,比如上例按姓名長度排序的查詢,Jay和Tom、Mary和Dick,除非我們添加額外的ThenBy運算符:

                  IEnumerable<string> query = names.OrderBy(s => s.Length).ThenBy(s => s);
      // Result: { "Jay", "Tom", "Dick", "Mary", "Harry" };

      ThenBy只會對那些在前一次排序中擁有相同鍵值的elements進行重新排序,我們可以連接任意數量的ThenBy運算符:

                  // 先按長度排序,然后按第二個字符排序,再按第一個字符排序
      IEnumerable<string> query =
      names.OrderBy (s => s.Length).ThenBy (s => s[1]).ThenBy (s => s[0]);

      // 對應的查詢表達式語法為
      IEnumerable<string> query =
      from s in names
      orderby s.Length, s[1], s[0]
      select s;

      LINQ也提供了OrderByDescending和ThenByDescending運算符,用來按降序排列一個sequence。下面的LINQ-to-db查詢獲取的purchases先按price降序排列,對于相同的price則按Description字母順序排列:

                  var query = dataContext.Purchases.OrderByDescending (p => p.Price)
      .ThenBy (p => p.Description);

      // 查詢表達式語法
      var query = from p in dataContext.Purchases
      orderby p.Price descending, p.Description
      select p;

      比較器(Comparers)和排序規則(collations)

      對一個本地查詢,鍵選擇器對象本身通過其默認的IComparable實現決定了排序算法,我們可以傳入一個IComparer對象來重載該排序算法。

                  // 排序時忽略大小寫
      names.OrderBy (n => n, StringComparer.CurrentCultureIgnoreCase);

      查詢表達式語法并不支持傳入comparer的做法,LINQ to SQL和EF也沒有任何方式來支持此功能。當我們查詢一個數據庫時,排序算法由排序列的collation(排序規則)決定。如果collation是大小寫敏感的,我們可以通過在鍵選擇器上調用ToUpper來獲得忽略大小寫的排序:

                  var query = from p in dataContext.Purchases
      orderby p.Description.ToUpper()
      select p;

      IOrderedEnumerable和IOrderedQueryable

      排序運算符 返回IEnumerable<T>的一個特殊子類型。Enumerable中的排序運算符返回

      IOrderedEnumerable;Queryable中的排序運算符返回IOrderedQueryable。這些子類型允許隨后的ThenBy運算符來進一步調整現有的排序,他們中定義的其他成員并沒有對用戶公開,所以他們看起來就像普通的sequence。僅當我們漸進的創建查詢時他們的區別才會顯現出來:

                  IOrderedEnumerable<string> query1 = names.OrderBy(s => s.Length);
      IOrderedEnumerable<string> query2 = query1.ThenBy(s => s);

      如果我們使用IEnumerable<string>來聲明query1,第二行就會編譯錯誤,因為ThenBy需要一個IOrderedEnumerable<string>的輸入類型。我們可以通過隱式類型變量來避免這種錯誤:

                  var query1 = names.OrderBy(s => s.Length);
      var query2 = query1.ThenBy(s => s);

      盡管如此,隱式類型有時候也會有其自身的問題,比如下面的查詢就不能編譯:

                  var query = names.OrderBy(s => s.Length);
      query = query.Where(n => n.Length > 3); // Compile-time error

      基于OrderBy的輸出類型,編譯器推斷出query的類型為IOrderedEnumerable<string>。但是下一行中的Where返回一個正常的IEnumerable<string>,所以它已不能重新賦值給query了。我們可以通過顯示類型定義或在OrderBy之后調用AsEnumerable()來作為一種變通的方案:

                  var query = names.OrderBy(s => s.Length).AsEnumerable();
      query = query.Where(n => n.Length > 3); // OK

      相應的,針對解釋查詢,我們需要調用AsQueryable。

       

      分組/Grouping

      IEnumerable<TSource>→IEnumerable<IGrouping<TSource,TElement>>

      Operator

      說明

      SQL語義

      GroupBy

      對一個sequence進行分組

      GROUP BY

      GroupBy

      參數

      類型

      Input sequence

      IEnumerable<TSource>

      鍵選擇器/Key selector

      TSource => TKey

      元素選擇器/Element selector(optional)

      TSource => TElement

      比較器/Comparer (optional)

      IEqualityComparer<TKey>

      查詢表達式語法

                      group element-expression by key-expression

      簡介

      GroupBy把一個平展的輸入sequence進行分組存放到輸出sequence中,比如下面的示例對C:\temp目錄下的文件按擴展名進行分組:

                  string[] files = Directory.GetFiles("c:\\temp");

      IEnumerable<IGrouping<string, string>> query =
      files.GroupBy(file => Path.GetExtension(file));

      // 使用匿名類型來存儲結果
      var query2 = files.GroupBy(file => Path.GetExtension(file));

      // 遍歷結果的方式
      foreach (IGrouping<string, string> grouping in query)
      {
      Console.WriteLine("Extension: " + grouping.Key);
      foreach (string filename in grouping)
      Console.WriteLine(" - " + filename);
      }

      // Result:
      Extension: .pdf
      - chapter03.pdf
      - chapter04.pdf
      Extension: .doc
      - todo.doc
      - menu.doc
      - Copy of menu.doc
      ...

      Enumerable.GroupBy會讀取每一個輸入element,把他們存放到一個臨時的列表dictionary,所有具有相同key的元素會被存入同一個子列表。然后返回一個分組(grouping)sequence,一個分組是一個帶有Key屬性的sequence

          public interface IGrouping<TKey, TElement>
      : IEnumerable<TElement>, IEnumerable
      {
      TKey Key { get; } // 一個subsequence共享一個Key屬性
      }

      默認情況下,每個分組里面的element都是沒有經過轉換的輸入element,除非你指定了元素選擇器參數。下面就把輸入element轉換到大寫形式:

                  var query3 = files.GroupBy(
      file => Path.GetExtension(file),
      file => file.ToUpper());

      元素選擇器和鍵值選擇器是互相獨立的兩個概念,上面的例子中,盡管分組中的元素是大寫的,但是分組中的Key保持原來的大小寫形式:

                  // Result:
      Extension: .pdf
      - chapter03.PDF
      - chapter04.PDF
      Extension: .doc
      - todo.DOC
      - menu.DOC
      - Copy of menu.DOC
      ...

      值得注意的是,分組中的子集合并沒有進行排序的功能,他會保持原來的順序。如果需要對結果排序,我們需要添加OrderBy運算符:

                      files.GroupBy(file => Path.GetExtension(file), file => file.ToUpper())
      .OrderBy(grouping => grouping.Key);

      GroupBy的查詢表達式語法非常的簡單和直接:group element-expression by key-expression

      下面使用查詢表達式重寫上面的例子:

                  var query =
      from file in files
      group file.ToUpper() by Path.GetExtension(file);

      和select一樣,group也會結束一個查詢,除非我們增加了一個可以繼續查詢的子句:

                  var query =
      from file in files
      group file.ToUpper() by Path.GetExtension(file) into grouping
      orderby grouping.Key
      select grouping;

      續寫查詢對于group by運算符來說非常有用,因為我們很可能要對分組進行過濾等操作。

                  // 只選擇元素數量小于3的分組
      var query =
      from file in files
      group file.ToUpper() by Path.GetExtension(file) into grouping
      where grouping.Count() < 3
      select grouping;

      group by之后的where子句相當于SQL中的HAVING,它會應用到整個分組或subsequence,而不是單個元素。

      有時候,我們可能僅對分組的匯總感興趣,所以我們可以丟棄subsequence:

                  string[] votes = { "Bush", "Gore", "Gore", "Bush", "Bush" };
      IEnumerable<string> query = from vote in votes
      group vote by vote into g
      orderby g.Count() descending
      select g.Key;
      string winner = query.First(); // Bush

      LINQ to SQL和EF中的GroupBy

      Grouping在對數據庫進行查詢時其工作方式是一樣的。但是如果設置了關聯屬性,你會發現group的使用幾率不會像標準SQL中那么頻繁,因為關聯屬性已經為我們實現了特定的分組功能。例如,我們想要選擇至少有 兩個purchases的customers,我們并不需要分組,下面的查詢就可以工作得很好:

                  var query =
      from c in dataContext.Customers
      where c.Purchases.Count >= 2
      select c.Name + " has made " + c.Purchases.Count + " purchases";

      下面是一個使用group的例子:

                  // 對銷售額按年份分組
      var query = from p in dataContext.Purchases
      group p.Price by p.Date.Year into salesByYear
      select new {
      Year = salesByYear.Key,
      TotalValue = salesByYear.Sum()
      };

      按多鍵值分組

      我們可以按一個復合鍵值進行分組,方式是使用一個匿名類型來表示這個鍵值:

                  // 對purchase按年月分組
      var query = from p in dataContext.Purchases
      group p by new { Year = p.Date.Year, Month = p.Date.Month };

       

      至此,LINQ Operators我們已經介紹了過濾、數據轉換、連接、排序和分組。關于LINQ Operators,在接下來的最后兩篇中,會討論其他還沒講述的運算符,包括:Set、Zip、轉換方法、Element運算符、集合方法、量詞(Quantifiers)生成方法(Generation Methods)。

      posted @ 2011-11-25 09:32  Life a Poem  閱讀(11070)  評論(5)    收藏  舉報
      主站蜘蛛池模板: 日日摸天天爽天天爽视频| 国产免费视频一区二区| 人妻系列无码专区69影院| 最近中文字幕完整版hd| 国产小受被做到哭咬床单GV| 精品乱人伦一区二区三区| 国产AV无码专区亚洲AV紧身裤| 亚洲精品喷潮一区二区三区| 国产精品午夜福利小视频| 亚洲精品国男人在线视频| 无码专区 人妻系列 在线 | 在线 欧美 中文 亚洲 精品| 亚洲中文字幕无码一久久区| 久久精品国产亚洲AV麻| 治多县| av色国产色拍| 日本道不卡一二三区视频| 国产区成人精品视频| 成年无码av片在线蜜芽| 国产极品粉嫩尤物一线天| 亚洲中文久久久久久精品国产| 一区二区免费高清观看国产丝瓜| 成人免费精品网站在线观看影片| 在线a级毛片无码免费真人| 亚洲国产大胸一区二区三区| 国产美女精品自在线拍免费| 永久黄网站色视频免费直播| 成人国产精品中文字幕| 日本一道本高清一区二区| 福利成人午夜国产一区| 亚洲女同精品久久女同| 亚洲色大成网站www久久九九 | 成人亚洲欧美一区二区三区| 亚洲成人av在线综合| 亚洲中文字幕无码久久2017| 亚洲一本大道在线| 国产97人人超碰CAO蜜芽PROM| 日本免费观看mv免费版视频网站| 精品一区二区三区蜜桃麻豆| 久久人人97超碰精品| av无码久久久久不卡网站蜜桃 |