如何用LINQ处理关联多Subject的Form列表并按指定字段分组?
问题描述
我有一组Form对象,每个Form通过关联表FormSubjectLink与Subject对象关联。如果某个Form关联多个Subject,如何用LINQ返回一个列表,让该Form按关联的每个Subject各出现一次并携带对应SubjectId?另外,如何将列表中拥有相同TypeId和SubjectId的Form进行分组?
复现场景的代码如下:
public class Form { public int Id { get; set; } public int TypeId { get; set; } public string Name { get; set; } public List<FormSubjectLink> FormSubjectLinks { get; set; } public int SubjectId { get; set; } // 用于存储拆分后的单个SubjectId } public class Subject { public int Id { get; set; } } public class FormSubjectLink { public int FormId { get; set; } public int SubjectId { get; set; } } public List<Form> forms = new List<Form>() { new Form { Id = 1, TypeId = 1, Name = "FormA1", FormSubjectLinks = new List<FormSubjectLink>() { new FormSubjectLink { FormId = 1, SubjectId = 1 } } }, new Form { Id = 2, TypeId = 1, Name = "FormA2", FormSubjectLinks = new List<FormSubjectLink>() { new FormSubjectLink { FormId = 2, SubjectId = 1 } } }, new Form { Id = 3, TypeId = 1, Name = "FormA3", FormSubjectLinks = new List<FormSubjectLink>() { new FormSubjectLink { FormId = 3, SubjectId = 2 } } }, new Form { Id = 4, TypeId = 2, Name = "FormB1", FormSubjectLinks = new List<FormSubjectLink>() { new FormSubjectLink { FormId = 4, SubjectId = 1 }, new FormSubjectLink { FormId = 4, SubjectId = 2 }}}};
期望处理后返回IEnumerable<IGrouping<(int TypeId, int SubjectId), Form>>类型的结果,统计结果如下:
| TypeId | SubjectId | Form Count |
|---|---|---|
| 1 | 1 | 2 |
| 1 | 2 | 1 |
| 2 | 1 | 1 |
| 2 | 2 | 1 |
解决方案
1. 拆分Form与Subject的关联
使用SelectMany方法将每个Form与其关联的FormSubjectLink展开,生成每个Form对应单个SubjectId的条目。为避免修改原Form对象,可通过投影创建新的Form实例。
2. 按TypeId和SubjectId分组
使用GroupBy方法,以元组(TypeId, SubjectId)作为分组键,对拆分后的条目进行分组,得到目标类型的结果。
完整代码实现
// 拆分并分组 var groupedForms = forms // 展开每个Form的关联Subject,生成带对应SubjectId的Form条目 .SelectMany(form => form.FormSubjectLinks.Select(link => new Form { Id = form.Id, TypeId = form.TypeId, Name = form.Name, FormSubjectLinks = form.FormSubjectLinks, SubjectId = link.SubjectId })) // 按(TypeId, SubjectId)分组 .GroupBy(form => (form.TypeId, form.SubjectId)); // 验证统计结果 foreach (var group in groupedForms) { Console.WriteLine($"TypeId: {group.Key.TypeId}, SubjectId: {group.Key.SubjectId}, Form Count: {group.Count()}"); }
代码说明
SelectMany:将每个Form的FormSubjectLinks集合拆分为单个条目,每个条目对应一个SubjectId,同时复制原Form的其他属性并设置SubjectId。GroupBy:以(TypeId, SubjectId)元组作为分组键,将具有相同键的Form条目归为一组,返回的结果类型与需求完全匹配。
内容的提问来源于stack exchange,提问作者Hannah Hayes
相关产品推荐
相关产品推荐

