将嵌套foreach循环转换为LINQ表达式的实现方案咨询
双List集合的LINQ改造方案
先帮你理清楚原代码的核心逻辑:
遍历每个讲师,再逐个检查学生,只要学生对应的模块名、讲师姓名和当前讲师匹配,就给讲师的
Credits加上该讲师的ModuleValueInCredits——简单说就是每匹配到一个对应学生,讲师学分就加一次模块学分值。
你之前的改造已经用LINQ筛选出了匹配的学生,但问题在于你修改了传入的studentList(这会破坏原始数据,非常不推荐),而且没完成关键的累加操作。下面给你两种符合LINQ风格的实现思路:
思路1:简化遍历+LINQ统计
这种方式保留了类似原代码的直观逻辑,但用LINQ替代内层循环的判断和统计,效率更高:
public void GetLecturersWorkloadStatistics(List<Student> studentList, List<Lecturer> lecturerList) { // 用LINQ的ForEach替代外层foreach循环 lecturerList.ForEach(lecturer => { // 统计当前讲师匹配的学生总数 var matchingStudentCount = studentList.Count(student => student.ModuleName == lecturer.ModuleName && student.LecturerLastName == lecturer.LastName && student.LecturerFirstName == lecturer.FirstName); // 直接计算总累加值(避免多次循环累加) lecturer.Credits += lecturer.ModuleValueInCredits * matchingStudentCount; }); }
思路2:纯LINQ关联+分组统计
如果想要更贴合LINQ的查询范式,可以用join关联两个集合,再分组统计,最后更新讲师学分:
public void GetLecturersWorkloadStatistics(List<Student> studentList, List<Lecturer> lecturerList) { // 用LINQ关联两个集合,按讲师分组统计匹配的学生数 var lecturerCreditUpdates = from lecturer in lecturerList join student in studentList on new { lecturer.ModuleName, lecturer.LastName, lecturer.FirstName } equals new { student.ModuleName, student.LecturerLastName, student.LecturerFirstName } group student by lecturer into groupedLecturer select new { TargetLecturer = groupedLecturer.Key, TotalCreditAdd = groupedLecturer.Count() * groupedLecturer.Key.ModuleValueInCredits }; // 遍历统计结果更新讲师学分 foreach (var update in lecturerCreditUpdates) { update.TargetLecturer.Credits += update.TotalCreditAdd; } }
关键提示
- 不要修改传入的
studentList:你之前的代码把studentList重新赋值为筛选后的列表,这会改变原始集合的内容,后续调用方使用这个集合时会出问题。 - 效率优化:原代码每匹配一个学生就累加一次,其实等价于「匹配学生数 × 模块学分值」,用
Count统计后直接计算总增量,比循环累加更高效。
内容的提问来源于stack exchange,提问作者Mantas Pranskūnas
相关产品推荐
相关产品推荐

