LINQ查詢運算式 - group by

 

十、group by

1、列出以 AssignedTo 為群組的所有問題單資料

using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            SampleData data = new SampleData();

            var query = from defect in SampleData.AllDefects
                        where defect.AssignedTo != null
                        group defect by defect.AssignedTo;

            foreach (var entry in query)
            {
                Console.WriteLine(entry.Key.Name);
                foreach (var defect in entry)
                {
                    Console.WriteLine("  ({0}) {1}",
                                      defect.Severity,
                                      defect.Summary);
                }
                Console.WriteLine();
            }
        }
    }
}

執行結果為

說明:

這時於 query 的時候,將會產生內含有 IGrouping 泛型的集合物件,

上圖可知 entry 是 IGrouping<User,Defeat> 型別,

每一個 entry 就是指一個 AssignedTo 人員,為什麼是 AssignedTo 呢?

因為當初就是以 AssignedTo 為群組的呀。

你還可以用 IGrouping<User,Defeat> 的 Key 屬性去取出以 AssignedTo 為群組的人名。

由上圖也得知每一組 AssignedTo 人員將會負責多筆問題單,可使用 foreach 去把他迭代出來。

 

2、查詢接續 into 改寫

上例也可以使用 into 關鍵字來改寫,其結果都是相同的。

using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            SampleData data = new SampleData();

            var query = from defect in SampleData.AllDefects
                        where defect.AssignedTo != null
                        group defect by defect.AssignedTo into grouped
                        select new
                        {
                            AssignedToName = grouped.Key.Name,
                            defects = grouped
                        };

            foreach (var entry in query)
            {
                Console.WriteLine(entry.AssignedToName);
                foreach (var defect in entry.defects)
                {
                    Console.WriteLine("  ({0}) {1}",
                                      defect.Severity,
                                      defect.Summary);
                }
                Console.WriteLine();
            }
        }
    }
}

其結果為

說明:

into 的作用為將 query 結果投影到一個名為 grouped 的範圍變數,

然後可用 select 關鍵字來包裝成最終要吐出的結果。

 

3、子查詢改寫

承上例也可以使用子查詢來改寫,其結果都是相同的。

using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            SampleData data = new SampleData();

            var query = from grouped in (
                        from defect in SampleData.AllDefects
                        where defect.AssignedTo != null
                        group defect by defect.AssignedTo
                        )
                        select new
                        {
                            AssignedToName = grouped.Key.Name,
                            defects = grouped
                        };

            foreach (var entry in query)
            {
                Console.WriteLine(entry.AssignedToName);
                foreach (var defect in entry.defects)
                {
                    Console.WriteLine("  ({0}) {1}",
                                      defect.Severity,
                                      defect.Summary);
                }
                Console.WriteLine();
            }
        }
    }
}

 

4、分成兩段來改寫

承上例也可以分成兩段來改寫,其結果都是相同的。

using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            SampleData data = new SampleData();

            var tmp = from defect in SampleData.AllDefects
                      where defect.AssignedTo != null
                      group defect by defect.AssignedTo;

            var query = from grouped in tmp
                        select new
                        {
                            AssignedToName = grouped.Key.Name,
                            defects = grouped
                        };

            foreach (var entry in query)
            {
                Console.WriteLine(entry.AssignedToName);
                foreach (var defect in entry.defects)
                {
                    Console.WriteLine("  ({0}) {1}",
                                      defect.Severity,
                                      defect.Summary);
                }
                Console.WriteLine();
            }
        }
    }
}

說明:

分成兩段寫乍看之下會讓人覺得很 low,其實不然,

分成兩段的好處更是讓他人看得懂、好理解也是很重要的。