C# LINQ Select 和 SelectMany 方法介紹

Select

Select 很好理解,就和平時使用 SQL 中的 select 一樣,就是選取要的部分。

例如我們有個物件「學生」
    
/// <summary>
/// 學生
/// </summary>
/// <param name="No">學號</param>
/// <param name="Name">姓名</param>
public record Student(string No, string Name);
    

學生清單如下:
    
Student[] students =
{
    new ("001", "小明"),
    new ("002", "大頭"),
    new ("003", "張三"),
    new ("004", "李四"),
    new ("005", "王五"),
};
    

這裡面每筆資料都有「學號」和「姓名」,如果只想要保留學號的話就可以使用 Select :
    
IEnumerable<string> select = students.Select(x=>x.No);
    


或是利用 Select 將資料重新排列組合,轉換為自己想要的樣子:
    
var list = students.Select(x => new { 學號 = x.No, 姓名 = x.Name }) .ToList();
list.ForEach(Console.WriteLine);

/*
{ 學號 = 001, 姓名 = 小明 }
{ 學號 = 002, 姓名 = 大頭 }
{ 學號 = 003, 姓名 = 張三 }
{ 學號 = 004, 姓名 = 李四 }
{ 學號 = 005, 姓名 = 王五 }
*/
    

SelectMany

而 SelectMany 則是將兩部分「相乘」

例如我們再有個物件「課程」
    
/// <summary>
/// 課程
/// </summary>
/// <param name="Id">課程代號</param>
/// <param name="Name">課程名稱</param>
public record Course(string Id, string Name);
    

課程清單如下:
    
Course[] courses =
{
    new ("001", "數學"),
    new ("002", "國文"),
};
    

使用 SelectMany 後就會將學生「乘以」課程:
    
var list = courses.SelectMany(x => students, (x, y) => new { x, y }).ToList();
list.ForEach(Console.WriteLine);

/*
{ x = Course { Id = 001, Name = 數學 }, y = Student { No = 001, Name = 小明 } }
{ x = Course { Id = 001, Name = 數學 }, y = Student { No = 002, Name = 大頭 } }
{ x = Course { Id = 001, Name = 數學 }, y = Student { No = 003, Name = 張三 } }
{ x = Course { Id = 001, Name = 數學 }, y = Student { No = 004, Name = 李四 } }
{ x = Course { Id = 001, Name = 數學 }, y = Student { No = 005, Name = 王五 } }
{ x = Course { Id = 002, Name = 國文 }, y = Student { No = 001, Name = 小明 } }
{ x = Course { Id = 002, Name = 國文 }, y = Student { No = 002, Name = 大頭 } }
{ x = Course { Id = 002, Name = 國文 }, y = Student { No = 003, Name = 張三 } }
{ x = Course { Id = 002, Name = 國文 }, y = Student { No = 004, Name = 李四 } }
{ x = Course { Id = 002, Name = 國文 }, y = Student { No = 005, Name = 王五 } }
*/
    

再稍微整理一下:
    
var list = courses.SelectMany(x => students, (x, y) =>
    new { 課程代號 = x.Id, 課程名稱 = x.Name, 學號 = y.No, 姓名 = y.Name }).ToList();
list.ForEach(Console.WriteLine);

/*
{ 課程代號 = 001, 課程名稱 = 數學, 學號 = 001, 姓名 = 小明 }
{ 課程代號 = 001, 課程名稱 = 數學, 學號 = 002, 姓名 = 大頭 }
{ 課程代號 = 001, 課程名稱 = 數學, 學號 = 003, 姓名 = 張三 }
{ 課程代號 = 001, 課程名稱 = 數學, 學號 = 004, 姓名 = 李四 }
{ 課程代號 = 001, 課程名稱 = 數學, 學號 = 005, 姓名 = 王五 }
{ 課程代號 = 002, 課程名稱 = 國文, 學號 = 001, 姓名 = 小明 }
{ 課程代號 = 002, 課程名稱 = 國文, 學號 = 002, 姓名 = 大頭 }
{ 課程代號 = 002, 課程名稱 = 國文, 學號 = 003, 姓名 = 張三 }
{ 課程代號 = 002, 課程名稱 = 國文, 學號 = 004, 姓名 = 李四 }
{ 課程代號 = 002, 課程名稱 = 國文, 學號 = 005, 姓名 = 王五 }
*/
    

會了 SelectMany 之後要印個九九乘法表也可以一行就解決了!
    
Enumerable.Range(1, 9).SelectMany(x => Enumerable.Range(1, 9), (x, y) => $"{y}x{x}={x * y} {(y == 9 ? "\n" : "\t")}").ToList().ForEach(Console.Write);

/*
1x1=1   2x1=2   3x1=3   4x1=4   5x1=5   6x1=6   7x1=7   8x1=8   9x1=9
1x2=2   2x2=4   3x2=6   4x2=8   5x2=10  6x2=12  7x2=14  8x2=16  9x2=18
1x3=3   2x3=6   3x3=9   4x3=12  5x3=15  6x3=18  7x3=21  8x3=24  9x3=27
1x4=4   2x4=8   3x4=12  4x4=16  5x4=20  6x4=24  7x4=28  8x4=32  9x4=36
1x5=5   2x5=10  3x5=15  4x5=20  5x5=25  6x5=30  7x5=35  8x5=40  9x5=45
1x6=6   2x6=12  3x6=18  4x6=24  5x6=30  6x6=36  7x6=42  8x6=48  9x6=54
1x7=7   2x7=14  3x7=21  4x7=28  5x7=35  6x7=42  7x7=49  8x7=56  9x7=63
1x8=8   2x8=16  3x8=24  4x8=32  5x8=40  6x8=48  7x8=56  8x8=64  9x8=72
1x9=9   2x9=18  3x9=27  4x9=36  5x9=45  6x9=54  7x9=63  8x9=72  9x9=81
*/
    


延伸閱讀: C# LINQ 從 0 到 1 基礎教學

參考資料:
Microsoft.Learn - Enumerable.Select Method
Microsoft.Learn - Enumerable.SelectMany Method

留言