编辑
2025-10-11
C#
00

目录

Select 示例
SelectMany 示例
SelectMany 实例
总结

在 C# 的 LINQ 查询中,SelectSelectMany 经常使用来处理集合或可查询对象。两者有些相似之处,但也有明显区别:

Select:将集合中的每个元素映射(投影)到一个新的形式,最终返回与原集合长度相同的序列。

SelectMany:针对集合中的每个元素返回一个可枚举序列,然后将所有子序列“压平”(Flatten)为一个新的序列。

Select 示例

以下例子演示如何使用 Select 将字符串列表中的每个元素转换成大写形式:

C#
public class Program { public static void Main() { var fruits = new List<string> { "apple", "banana", "cherry" }; // 使用 Select 把每个字符串都转换为大写 var upperFruits = fruits.Select(fruit => fruit.ToUpper()); foreach (var item in upperFruits) { Console.WriteLine(item); } } }

image.png

fruits.Select(...) 将原始字符串映射为新的大写字符串。

• 结果数量和 fruits 中的元素数量相同,只有值发生了改变。

SelectMany 示例

下面示例演示如何使用 SelectMany 将一个“列表的列表”展平成单个列表。假设我们有三位学生,每位学生拥有多门课程:

C#
public class Program { public static void Main() { var studentsCourses = new List<List<string>> { new List<string> { "Math", "Physics" }, new List<string> { "History", "Literature", "Philosophy" }, new List<string> { "ComputerScience", "Statistics" } }; // 使用 SelectMany 将多层列表进行扁平化 var flattenedCourses = studentsCourses.SelectMany(courses => courses); foreach (var course in flattenedCourses) { Console.WriteLine(course); } } }

image.png

在这个示例中:

SelectMany 对每个子列表执行投影,然后将所有子列表合并成一个单一序列。

• 与 Select 的区别在于,如果使用 Select,最终结果会是一个列表(外层)里装着多个列表(内层);而 SelectMany 则直接展开为单层列表。


SelectMany 实例

将某一个月的项目自动补齐日期

C#
namespace AppSelectLinq { public class ProjectData { public DateTime Date { get; set; } public string Project { get; set; } public int Qty { get; set; } } public class Program { public static void Main() { // 假设的日期范围 var monthRange = Tuple.Create(new DateTime(2024, 12, 1), new DateTime(2024, 12, 31)); // 假设的项目数据列表 var lst = new List<ProjectData> { new ProjectData { Date = new DateTime(2024, 12, 1), Project = "Project A", Qty = 10 }, new ProjectData { Date = new DateTime(2024, 12, 1), Project = "Project B", Qty = 5 }, new ProjectData { Date = new DateTime(2024, 12, 2), Project = "Project A", Qty = 8 }, new ProjectData { Date = new DateTime(2024, 12, 3), Project = "Project C", Qty = 12 }, }; DateTime start2 = monthRange.Item1.Date; DateTime end2 = monthRange.Item2.Date; var allDates = Enumerable.Range(0, (end2 - start2).Days + 1) .Select(offset => start2.AddDays(offset)) .SelectMany(date => lst.Select(x => x.Project).Distinct() .Select(proj => new { Date = date, Project = proj, Qty = lst.FirstOrDefault(x => x.Date == date && x.Project == proj)?.Qty ?? 0 })) .ToList(); // 输出结果 foreach (var item in allDates) { Console.WriteLine($"Date: {item.Date.ToShortDateString()}, Project: {item.Project}, Qty: {item.Qty}"); } } } }

image.png


  • 定义了一个日期范围 monthRange
  • 创建了一个示例项目数据列表 lst,其中包含不同日期和项目的数量。
  • 使用 Enumerable.Range 生成从 start2end2 的所有日期。
  • 对于每个日期,使用 SelectMany 结合 Distinct 方法获取所有项目,并为每个项目创建一个匿名对象,包含日期、项目名称和数量(如果没有找到,则数量为 0)

总结

  • Select:一对一映射,返回与原序列长度相同的结果序列。
  • SelectMany:一对多映射,将子序列进行扁平化后返回一个单层序列。

它们是 LINQ 中非常常用的方法,合理使用它们有助于让你在处理复杂数据结构时写出更加简洁、可读的代码。

本文作者:技术老小子

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!