LINQ查詢表達式(3) - LINQ 查詢分組


對查詢結果進行分組

  分組是 LINQ 最強大的功能之一。

  下面的示例演示如何以各種方式對數據進行分組:

  • 按照單個屬性。
  • 按照字符串屬性的首字母。
  • 按照計算出的數值范圍。
  • 按照布爾謂詞或其他表達式。
  • 按照復合鍵。

  此外,最后兩個查詢將它們的結果投影到一個新的匿名類型中,該類型僅包含學生的名字和姓氏。

//單個屬性作為組鍵對源元素進行分組
 var queryLastNames =
                from student in students
                group student by student.LastName into newGroup
                orderby newGroup.Key
                select newGroup;

通過使用除對象屬性以外的某個項作為組鍵對源元素進行分組, 在此示例中,鍵是學生姓氏的第一個字母
  var queryFirstLetters =
                from student in students
                group student by student.LastName[0];

/*
通過使用某個數值范圍作為組鍵對源元素進行分組。 然后,查詢將結果投影到一個匿名類型中,該類型僅包含學生的名字和姓氏以及該學生所屬的百分點范圍。 使用匿名類型的原因是沒有必要使用完整的 Student 對象來顯示結果。*/
Helper method, used in GroupByRange.
        protected static int GetPercentile(Student s)
        {
            double avg = s.ExamScores.Average();
            return avg > 0 ? (int)avg / 10 : 0;
        }

  var queryNumericRange =
                from student in students
                let percentile = GetPercentile(student)
                group new { student.FirstName, student.LastName } by percentile into percentGroup
                orderby percentGroup.Key
                select percentGroup;

//通過使用布爾比較表達式對源元素進行分組
  var queryGroupByAverages = from student in students
                                       group new { student.FirstName, student.LastName }
                                            by student.ExamScores.Average() > 75 into studentGroup
                                       select studentGroup;

/*
下面的示例演示如何使用匿名類型來封裝包含多個值的鍵。 在此示例中,第一個鍵值是學生姓氏的第一個字母。 第二個鍵值是一個布爾值,它指定該學生在第一次考試中的得分是否超過了 85。 可以按照該鍵中的任何屬性對多組值進行排序。*/
 var queryHighScoreGroups =
                from student in students
                group student by new { FirstLetter = student.LastName[0], 
                    Score = student.ExamScores[0] > 85 } into studentGroup
                orderby studentGroup.Key.FirstLetter
                select studentGroup;

 創建嵌套分組

      public void QueryNestedGroups()
        {
            var queryNestedGroups =
                from student in students
                group student by student.Year into newGroup1
                from newGroup2 in
                    (from student in newGroup1
                     group student by student.LastName)
                group newGroup2 by newGroup1.Key;

            // Three nested foreach loops are required to iterate 
            // over all elements of a grouped group. Hover the mouse 
            // cursor over the iteration variables to see their actual type.
            foreach (var outerGroup in queryNestedGroups)
            {
                Console.WriteLine("DataClass.Student Level = {0}", outerGroup.Key);
                foreach (var innerGroup in outerGroup)
                {
                    Console.WriteLine("\tNames that begin with: {0}", innerGroup.Key);
                    foreach (var innerGroupElement in innerGroup)
                    {
                        Console.WriteLine("\t\t{0} {1}", innerGroupElement.LastName, innerGroupElement.FirstName);
                    }
                }
            }
        }

 

   分組數據類型IGrouping接口:

namespace System.Linq
{ 
    public interface IGrouping<out TKey, out TElement> : IEnumerable<TElement>, IEnumerable { TKey Key { get; } }   public interface ILookup<TKey, TElement> : IEnumerable<IGrouping<TKey, TElement>>, IEnumerable { IEnumerable<TElement> this[TKey key] { get; } int Count { get; } bool Contains(TKey key); } }

 對分組操作執行子查詢

  創建一個查詢,以便將源數據排序到不同的組中,然后分別對每個組執行子查詢。

  每個示例中的基本技術都是使用一個名為 studentGroup 的“延續”對源元素進行分組,然后生成一個針對 studentGroup的新的子查詢。 此子查詢是針對外部查詢所創建的每個新組運行的。

  請注意,在此特定示例中,最終的輸出不是組,而是匿名類型的平面序列,代碼如下:

    public void QueryMax()
        {
            var queryGroupMax =
                from student in students
                group student by student.Year into studentGroup
                select new
                {
                    Level = studentGroup.Key,
                    HighestScore =
                    (from student2 in studentGroup
                     select student2.ExamScores.Average()).Max()
                };

            int count = queryGroupMax.Count();
            Console.WriteLine("Number of groups = {0}", count);

            foreach (var item in queryGroupMax)
            {
                Console.WriteLine("  {0} Highest Score={1}", item.Level, item.HighestScore);
            }
        }

參考

  [1]MSDN,對查詢結果進行分組


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM