c# - 如何使用 Linq 在某些操作中聚合两个 List?
问题描述
我已经定义了包含名称、主题属性的类 StudentData,这些属性是枚举类型,并且得分为双倍。一些数据填充在List结构StudentNameList和StudentDataList中。
public class StudentData
{
public StudentName Name { get; set; }
public Subject Subject { get; set; }
public double Score { get; set; }
public StudentData(StudentName name, Subject subject, double score)
{
Name = name;
Subject = subject;
Score = score;
}
}
public enum StudentName
{
Tom,
Nikki,
Benny
}
public enum Subject
{
Math,
Physic,
History
}
List<StudentName> studentName = new List<StudentName>();
studentName.Add( StudentName.Benny);
studentName.Add(StudentName.Nikki);
studentName.Add(StudentName.Tom);
List<StudentData> studentDataList = new List<StudentData>();
studentDataList.Add(new StudentData(StudentName.Benny, Subject.History, 85));
studentDataList.Add(new StudentData(StudentName.Benny, Subject.Math, 60));
studentDataList.Add(new StudentData(StudentName.Benny, Subject.Physic, 75));
studentDataList.Add(new StudentData(StudentName.Nikki, Subject.History, 65));
studentDataList.Add(new StudentData(StudentName.Nikki, Subject.Math, 70));
studentDataList.Add(new StudentData(StudentName.Nikki, Subject.Physic, 75));
studentDataList.Add(new StudentData(StudentName.Tom, Subject.History, 88));
studentDataList.Add(new StudentData(StudentName.Tom, Subject.Math, 90));
studentDataList.Add(new StudentData(StudentName.Tom, Subject.Physic, 95));
下面定义了因子表
List<double> FactorTable = new List<double>();
FactorTable.Add(1.05);
FactorTable.Add(1.02);
我想要实现的是创建一个 Dictionary<StudentName, Double> ,该值存储该学生的所有加权平均分数(将所有分数与因子列表相乘)。例如在本尼的案例中:
Dictionary<StudentName, double> StudentDic = new Dictionary<StudentName, double>();
键:Benny,值:(85 * 1.05) + (85 *1.02) + (60 * 1.05) + (60 * 1.02) + (75 * 1.05) + (75 * 1.02)
我认为这可以通过几个聚合 Linq 操作来完成。但是,当我开始实施时,这并不容易实现。我所做的如下:
foreach (var student in studentName)
{
var filterStudent = studentDataList.Where(s => s.Name == student);
List<double> multipledResult = new List<double>();
foreach (var s in filterStudent)
{
foreach (var f in FactorTable)
{
multipledResult.Add(s.Score * f);
}
}
StudentDic.Add(student, multipledResult.Average());
}
通过使用 Linq 操作来简化算法,我想念什么。有人可以建议是否有办法改进它?
解决方案
这应该给你一个起点:
var result =
studentDataList
.SelectMany(sdl => FactorTable.Select(ft => new {
sdl.Name,
aggScore = ft * sdl.Score
}))
.GroupBy(prod => prod.Name)
.Select(g => new {
Name = (StudentName)g.Key,
wtAvg = g.Sum(x => x.aggScore) / g.Sum(x => x.ft)
})
.ToDictionary(x => (StudentName)x.Name, x => x.wtAvg);
该SelectMany -> Select
方法通过每个权重为您提供每个分数的您想要的产品。然后链为每个人创建一个组。最终Select
总结了该组中的所有加权产品。如果您真的需要,最后一行会将其转换为字典。
但不要忘记,对于加权 AVERAGE,您还需要除以可能的总权重。
它给出了结果:
| Benny | 73.333... |
| Nikki | 70 |
| Tom | 91 |
本尼的分数基本上是通过以下方式得出的:
var num = (85 * 1.05) + (85 *1.02) + (60 * 1.05) + (60 * 1.02) + (75 * 1.05) + (75 * 1.02);
var den = 1.05 + 1.02 + 1.05 + 1.02 + 1.05 + 1.02;
var result = num / den; // 73.33333......
当然,如果你真的想要加权和,而不是加权平均,那么只需在最终的 select 方法中删除分母,并将 from 重命名为wtAvg
to wtSum
。
推荐阅读
- linux - 显示当前目录而不是父目录中的所有隐藏文件
- android - 如何在库模块中导入 .aar 库文件并导出为单个库?
- git - git - 用全局 .gitignore 覆盖 repo 的 .gitignore(对于机器)
- r - 更改按钮扩展中的分隔符
- python - python不同数量的键字典以指定格式存储到文本文件
- c++ - “boost::algorithm::trim”可以用于一般的前导或尾随空格,而不是使用它的左、右版本吗?
- c# - 如何从 C# 通过 Teams 拨打电话
- jenkins - 后管道故障的代码执行失败
- javascript - 如何从 Javascript 数组中删除元素?
- php - 查询输出中缺少 DATETIME 值,然后自动填充该缺失值并获得正确的输出