在 C# 的 LINQ 查询中,Select
与 SelectMany
经常使用来处理集合或可查询对象。两者有些相似之处,但也有明显区别:
Select
:将集合中的每个元素映射(投影)到一个新的形式,最终返回与原集合长度相同的序列。
SelectMany
:针对集合中的每个元素返回一个可枚举序列,然后将所有子序列“压平”(Flatten)为一个新的序列。
以下例子演示如何使用 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);
}
}
}
• fruits.Select(...)
将原始字符串映射为新的大写字符串。
• 结果数量和 fruits
中的元素数量相同,只有值发生了改变。
下面示例演示如何使用 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);
}
}
}
在这个示例中:
• SelectMany
对每个子列表执行投影,然后将所有子列表合并成一个单一序列。
• 与 Select
的区别在于,如果使用 Select
,最终结果会是一个列表(外层)里装着多个列表(内层);而 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}");
}
}
}
}
monthRange
。lst
,其中包含不同日期和项目的数量。Enumerable.Range
生成从 start2
到 end2
的所有日期。SelectMany
结合 Distinct
方法获取所有项目,并为每个项目创建一个匿名对象,包含日期、项目名称和数量(如果没有找到,则数量为 0)Select
:一对一映射,返回与原序列长度相同的结果序列。SelectMany
:一对多映射,将子序列进行扁平化后返回一个单层序列。它们是 LINQ 中非常常用的方法,合理使用它们有助于让你在处理复杂数据结构时写出更加简洁、可读的代码。
本文作者:技术老小子
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!