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,其實不然,
分成兩段的好處更是讓他人看得懂、好理解也是很重要的。